using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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+0279a075331163a6f6080307565f05ae429bc45b")]
[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
{
[HarmonyPatch]
public static class CartographyTablePatch
{
private static string DiscordHint
{
get
{
//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)
KeyCode value = Plugin.ScreenshotKey.Value;
return "\n[<color=yellow><b>" + ((object)(KeyCode)(ref value)).ToString() + "</b></color>] Send Map to Discord";
}
}
[HarmonyPatch(typeof(MapTable), "GetReadHoverText")]
[HarmonyPostfix]
private static void GetReadHoverText_Postfix(ref string __result)
{
if (!string.IsNullOrEmpty(Plugin.WebhookUrl.Value))
{
__result += DiscordHint;
}
}
[HarmonyPatch(typeof(MapTable), "GetWriteHoverText")]
[HarmonyPostfix]
private static void GetWriteHoverText_Postfix(ref string __result)
{
if (!string.IsNullOrEmpty(Plugin.WebhookUrl.Value))
{
__result += DiscordHint;
}
}
}
public static class DiscordButton
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__2_0;
internal void <Create>b__2_0()
{
Plugin instance = Plugin.Instance;
if (!((Object)(object)instance == (Object)null))
{
instance.TriggerDiscordSend();
}
}
}
private static GameObject _buttonObj;
private static Button _cachedRefButton;
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_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: 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_00c6: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: 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_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: 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)_buttonObj != (Object)null)
{
return;
}
_buttonObj = new GameObject("DiscordScreenshotBtn");
_buttonObj.transform.SetParent(transform, false);
RectTransform obj = _buttonObj.AddComponent<RectTransform>();
obj.anchorMin = new Vector2(1f, 0f);
obj.anchorMax = new Vector2(1f, 0f);
obj.pivot = new Vector2(1f, 0f);
obj.anchoredPosition = new Vector2(-20f, 20f);
obj.sizeDelta = new Vector2(140f, 38f);
Image val = _buttonObj.AddComponent<Image>();
Button val2 = _buttonObj.AddComponent<Button>();
((Selectable)val2).targetGraphic = (Graphic)(object)val;
ApplyValheimStyle(val, val2);
GameObject val3 = new GameObject("Text");
val3.transform.SetParent(_buttonObj.transform, false);
RectTransform obj2 = val3.AddComponent<RectTransform>();
obj2.anchorMin = Vector2.zero;
obj2.anchorMax = Vector2.one;
obj2.offsetMin = new Vector2(8f, 4f);
obj2.offsetMax = new Vector2(-8f, -4f);
TextMeshProUGUI obj3 = val3.AddComponent<TextMeshProUGUI>();
((TMP_Text)obj3).text = "CAPTURE";
((TMP_Text)obj3).alignment = (TextAlignmentOptions)514;
ApplyValheimFont(obj3);
ButtonClickedEvent onClick = val2.onClick;
object obj4 = <>c.<>9__2_0;
if (obj4 == null)
{
UnityAction val4 = delegate
{
Plugin instance2 = Plugin.Instance;
if (!((Object)(object)instance2 == (Object)null))
{
instance2.TriggerDiscordSend();
}
};
<>c.<>9__2_0 = val4;
obj4 = (object)val4;
}
((UnityEvent)onClick).AddListener((UnityAction)obj4);
_buttonObj.SetActive(true);
RefreshEnabledState();
Debug.Log((object)"[NoMapDiscordAdditions] Discord screenshot button created on map UI.");
}
public static void RefreshEnabledState()
{
if (!((Object)(object)_buttonObj == (Object)null))
{
Button component = _buttonObj.GetComponent<Button>();
if (!((Object)(object)component == (Object)null))
{
bool interactable = Plugin.WebhookUrl != null && !string.IsNullOrEmpty(Plugin.WebhookUrl.Value);
((Selectable)component).interactable = interactable;
}
}
}
public static void SetVisible(bool visible)
{
if (!((Object)(object)_buttonObj == (Object)null))
{
_buttonObj.SetActive(visible);
if (visible)
{
RefreshEnabledState();
}
}
}
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 == "DiscordScreenshotBtn" || ((Object)child).name == "DiscordScreenshotBtnV2"))
{
Object.Destroy((Object)(object)((Component)child).gameObject);
}
}
if (!Object.op_Implicit((Object)(object)_buttonObj))
{
_buttonObj = null;
}
}
private static void ApplyValheimStyle(Image image, Button button)
{
//IL_0024: 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_0089: 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_004d: 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)
Button val = FindReferenceButton();
if ((Object)(object)val == (Object)null)
{
((Graphic)image).color = new Color(0f, 0f, 0f, 0.6f);
return;
}
Image component = ((Component)val).GetComponent<Image>();
if ((Object)(object)component != (Object)null)
{
image.sprite = component.sprite;
image.type = component.type;
((Graphic)image).material = ((Graphic)component).material;
((Graphic)image).color = ((Graphic)component).color;
image.pixelsPerUnitMultiplier = component.pixelsPerUnitMultiplier;
}
((Selectable)button).transition = ((Selectable)val).transition;
((Selectable)button).colors = ((Selectable)val).colors;
((Selectable)button).spriteState = ((Selectable)val).spriteState;
}
private static void ApplyValheimFont(TextMeshProUGUI text)
{
//IL_00e0: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
TMP_Text val = null;
Button val2 = FindReferenceButton();
if ((Object)(object)val2 != (Object)null)
{
val = ((Component)val2).GetComponentInChildren<TMP_Text>(true);
}
if ((Object)(object)val == (Object)null || (Object)(object)val.font == (Object)null)
{
TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
foreach (TMP_Text val3 in array)
{
if ((Object)(object)val3 != (Object)null && (Object)(object)val3.font != (Object)null)
{
val = val3;
break;
}
}
}
Color color = default(Color);
((Color)(ref color))..ctor(1f, 0.631f, 0.235f, 1f);
if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null)
{
((TMP_Text)text).font = val.font;
((TMP_Text)text).fontSize = val.fontSize;
((TMP_Text)text).fontStyle = val.fontStyle;
((Graphic)text).color = color;
}
else
{
Debug.LogWarning((object)"[NoMapDiscordAdditions] No TMP_FontAsset found — capture button label will not render.");
((TMP_Text)text).fontSize = 16f;
((Graphic)text).color = color;
}
}
private static Button FindReferenceButton()
{
if ((Object)(object)_cachedRefButton != (Object)null)
{
return _cachedRefButton;
}
Button[] array = Resources.FindObjectsOfTypeAll<Button>();
foreach (Button val in array)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Image component = ((Component)val).GetComponent<Image>();
if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sprite == (Object)null))
{
string text = ((Object)component.sprite).name ?? string.Empty;
if (text == "button" || text.StartsWith("button_"))
{
_cachedRefButton = val;
return val;
}
}
}
return null;
}
}
public static class DiscordWebhook
{
public static IEnumerator SendImage(byte[] imageData, string filename, string message, bool useSpoilerTag)
{
string value = Plugin.WebhookUrl.Value;
if (string.IsNullOrEmpty(value))
{
Debug.LogWarning((object)"[NoMapDiscordAdditions] Webhook URL not configured.");
yield break;
}
WWWForm val = new WWWForm();
val.AddBinaryData("files[0]", imageData, GetAttachmentFileName(filename, useSpoilerTag), "image/jpeg");
if (!string.IsNullOrEmpty(message))
{
val.AddField("payload_json", "{\"content\":\"" + EscapeJson(message) + "\"}");
}
UnityWebRequest request = UnityWebRequest.Post(value, val);
try
{
yield return request.SendWebRequest();
if ((int)request.result != 1)
{
Debug.LogError((object)("[NoMapDiscordAdditions] Discord webhook failed: " + request.error));
}
else
{
Debug.Log((object)"[NoMapDiscordAdditions] Map screenshot sent to Discord.");
}
}
finally
{
((IDisposable)request)?.Dispose();
}
}
private static string EscapeJson(string text)
{
return text.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n")
.Replace("\r", "\\r");
}
private static string GetAttachmentFileName(string filename, bool useSpoilerTag)
{
if (!useSpoilerTag || string.IsNullOrEmpty(filename) || filename.StartsWith("SPOILER_"))
{
return filename;
}
return "SPOILER_" + filename;
}
}
public static class MapCapture
{
private struct SavedProp
{
public string Name;
public ShaderPropertyType Type;
public Texture Tex;
public float Float;
public Color Color;
public Vector4 Vec;
}
private static readonly FieldInfo _mapLargeShaderField = AccessTools.Field(typeof(Minimap), "m_mapLargeShader");
public static IEnumerator CaptureVisibleMap(Action<byte[]> callback)
{
Minimap minimap = Minimap.instance;
if ((Object)(object)minimap == (Object)null || (int)minimap.m_mode != 2)
{
callback(null);
yield break;
}
int num = (ServerSyncCompat.IsActive ? Plugin.CaptureSuperSize.Value : NetworkConfigSync.EffectiveCaptureSuperSize);
int superSize = Mathf.Clamp(num, 1, 4);
List<MinimapButtonCaptureSuppressor.SavedActive> suppressedButtons = MinimapButtonCaptureSuppressor.Begin(minimap);
bool num2 = (ServerSyncCompat.IsActive ? Plugin.HideClouds.Value : NetworkConfigSync.EffectiveHideClouds);
List<SavedProp> savedClouds = null;
Material mapMaterial = GetMapMaterial(minimap);
if (num2 && (Object)(object)mapMaterial != (Object)null)
{
savedClouds = SuppressClouds(mapMaterial);
}
try
{
yield return (object)new WaitForEndOfFrame();
Texture2D val = null;
try
{
val = ScreenCapture.CaptureScreenshotAsTexture(superSize);
}
catch (Exception ex)
{
Debug.LogError((object)("[NoMapDiscordAdditions] Screen capture failed: " + ex.Message));
}
if ((Object)(object)val == (Object)null)
{
callback(null);
yield break;
}
Texture2D val2 = CropToMapRect(minimap, val, superSize);
Texture2D val3 = val2 ?? val;
byte[] obj = null;
try
{
obj = ImageConversion.EncodeToPNG(val3);
}
catch (Exception ex2)
{
Debug.LogError((object)("[NoMapDiscordAdditions] PNG encode failed: " + ex2.Message));
}
finally
{
Object.Destroy((Object)(object)val);
if ((Object)(object)val2 != (Object)null)
{
Object.Destroy((Object)(object)val2);
}
}
callback(obj);
}
finally
{
MinimapButtonCaptureSuppressor.End(suppressedButtons);
if (savedClouds != null && (Object)(object)mapMaterial != (Object)null)
{
RestoreClouds(mapMaterial, savedClouds);
}
DiscordButton.SetVisible((int)minimap.m_mode == 2);
}
}
private static Material GetMapMaterial(Minimap minimap)
{
if ((Object)(object)minimap == (Object)null)
{
return null;
}
object? obj = _mapLargeShaderField?.GetValue(minimap);
Material val = (Material)((obj is Material) ? obj : null);
if ((Object)(object)val != (Object)null)
{
return val;
}
if (!((Object)(object)minimap.m_mapImageLarge != (Object)null))
{
return null;
}
return ((Graphic)minimap.m_mapImageLarge).material;
}
private static List<SavedProp> SuppressClouds(Material mat)
{
//IL_005e: 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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: 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_009e: Expected I4, but got Unknown
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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)
List<SavedProp> list = new List<SavedProp>();
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("cloud", StringComparison.OrdinalIgnoreCase) >= 0)
{
ShaderPropertyType propertyType = shader.GetPropertyType(i);
SavedProp savedProp = default(SavedProp);
savedProp.Name = propertyName;
savedProp.Type = propertyType;
SavedProp item = savedProp;
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;
}
private static void RestoreClouds(Material mat, List<SavedProp> 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 (SavedProp 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;
}
}
}
private static Texture2D CropToMapRect(Minimap minimap, Texture2D screen, int superSize)
{
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Expected O, but got Unknown
RawImage mapImageLarge = minimap.m_mapImageLarge;
if ((Object)(object)mapImageLarge == (Object)null)
{
return null;
}
RectTransform rectTransform = ((Graphic)mapImageLarge).rectTransform;
Vector3[] array = (Vector3[])(object)new Vector3[4];
rectTransform.GetWorldCorners(array);
float num = Mathf.Min(array[0].x, array[2].x) * (float)superSize;
float num2 = Mathf.Min(array[0].y, array[2].y) * (float)superSize;
float num3 = Mathf.Max(array[0].x, array[2].x) * (float)superSize;
float num4 = Mathf.Max(array[0].y, array[2].y) * (float)superSize;
int num5 = Mathf.Clamp(Mathf.RoundToInt(num), 0, ((Texture)screen).width - 1);
int num6 = Mathf.Clamp(Mathf.RoundToInt(num2), 0, ((Texture)screen).height - 1);
int num7 = Mathf.Clamp(Mathf.RoundToInt(num3) - num5, 1, ((Texture)screen).width - num5);
int num8 = Mathf.Clamp(Mathf.RoundToInt(num4) - num6, 1, ((Texture)screen).height - num6);
try
{
Color[] pixels = screen.GetPixels(num5, num6, num7, num8);
Texture2D val = new Texture2D(num7, num8, (TextureFormat)3, false);
val.SetPixels(pixels);
val.Apply();
return val;
}
catch (Exception ex)
{
Debug.LogWarning((object)("[NoMapDiscordAdditions] Crop failed, sending full screen: " + ex.Message));
return null;
}
}
}
public static class MapCaptureTexture
{
private struct SavedProp
{
public string Name;
public ShaderPropertyType Type;
public Texture Tex;
public float Float;
public Color Color;
public Vector4 Vec;
}
private static readonly FieldInfo _mapTextureField = AccessTools.Field(typeof(Minimap), "m_mapTexture");
private static readonly FieldInfo _mapImageLargeField = AccessTools.Field(typeof(Minimap), "m_mapImageLarge");
private static readonly FieldInfo _pinRootLargeField = AccessTools.Field(typeof(Minimap), "m_pinRootLarge");
private static readonly FieldInfo _largeMarkerField = AccessTools.Field(typeof(Minimap), "m_largeMarker");
private static readonly FieldInfo _largeShipMarkerField = AccessTools.Field(typeof(Minimap), "m_largeShipMarker");
private static readonly FieldInfo _mapLargeShaderField = AccessTools.Field(typeof(Minimap), "m_mapLargeShader");
private const int OutputWidth = 1920;
private const int OutputHeight = 1080;
public static byte[] CaptureMap()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
Minimap instance = Minimap.instance;
if ((Object)(object)instance == (Object)null || (int)instance.m_mode != 2)
{
Debug.LogError((object)"[NoMapDiscordAdditions] Large map not active.");
return null;
}
object? obj = _mapTextureField?.GetValue(instance);
Texture2D val = (Texture2D)((obj is Texture2D) ? obj : null);
object? obj2 = _mapImageLargeField?.GetValue(instance);
RawImage val2 = (RawImage)((obj2 is RawImage) ? obj2 : null);
object? obj3 = _pinRootLargeField?.GetValue(instance);
RectTransform val3 = (RectTransform)((obj3 is RectTransform) ? obj3 : null);
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
Debug.LogError((object)"[NoMapDiscordAdditions] Required Minimap fields not available.");
return null;
}
object? obj4 = _mapLargeShaderField?.GetValue(instance);
Material val4 = (Material)((obj4 is Material) ? obj4 : null);
if ((Object)(object)val4 == (Object)null)
{
val4 = ((Graphic)val2).material;
}
RectTransform rectTransform = ((Graphic)val2).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)
{
Debug.LogError((object)"[NoMapDiscordAdditions] Map RectTransform has zero size.");
return null;
}
List<MinimapButtonCaptureSuppressor.SavedActive> saved = MinimapButtonCaptureSuppressor.Begin(instance);
try
{
RenderTexture temporary = RenderTexture.GetTemporary(1920, 1080, 0, (RenderTextureFormat)0);
Color32[] array2;
try
{
DrawMapBase(temporary, val, val4, val2.uvRect);
array2 = ReadRTPixels(temporary);
}
finally
{
RenderTexture.ReleaseTemporary(temporary);
}
if (array2 == null)
{
Debug.LogError((object)"[NoMapDiscordAdditions] GPU pass failed.");
return null;
}
if ((Object)(object)val3 != (Object)null)
{
BlitUIChildren(array2, x, y, num, num2, (Transform)(object)val3);
}
BlitMarker(instance, _largeMarkerField, array2, x, y, num, num2);
BlitMarker(instance, _largeShipMarkerField, array2, x, y, num, num2);
return Encode(array2);
}
finally
{
MinimapButtonCaptureSuppressor.End(saved);
}
}
private static void DrawMapBase(RenderTexture target, Texture2D mapTex, Material mat, Rect uv)
{
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
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);
bool flag = (ServerSyncCompat.IsActive ? Plugin.HideClouds.Value : NetworkConfigSync.EffectiveHideClouds);
List<SavedProp> list = null;
Texture val = null;
bool flag2 = (Object)(object)mat != (Object)null && mat.HasProperty("_MainTex");
if (flag && (Object)(object)mat != (Object)null)
{
list = SuppressClouds(mat);
}
if (flag2)
{
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 flag3 = 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();
flag3 = true;
}
if (!flag3)
{
Graphics.Blit((Texture)(object)mapTex, target, new Vector2(num3 - num, num4 - num2), new Vector2(num, num2));
}
}
finally
{
RenderTexture.active = active;
if (flag2 && (Object)(object)val != (Object)null)
{
mat.SetTexture("_MainTex", val);
}
if (list != null)
{
RestoreClouds(mat, list);
}
}
}
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 List<SavedProp> SuppressClouds(Material mat)
{
//IL_005e: 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_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: 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_009e: Expected I4, but got Unknown
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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)
List<SavedProp> list = new List<SavedProp>();
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("cloud", StringComparison.OrdinalIgnoreCase) >= 0)
{
ShaderPropertyType propertyType = shader.GetPropertyType(i);
SavedProp savedProp = default(SavedProp);
savedProp.Name = propertyName;
savedProp.Type = propertyType;
SavedProp item = savedProp;
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;
}
private static void RestoreClouds(Material mat, List<SavedProp> 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 (SavedProp 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;
}
}
}
private static void BlitUIChildren(Color32[] output, 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<Image>();
if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled && (Object)(object)component.sprite != (Object)null)
{
BlitImage(output, mapMinX, mapMinY, mapW, mapH, val, component);
}
if (child.childCount > 0)
{
BlitUIChildren(output, mapMinX, mapMinY, mapW, mapH, child);
}
}
}
}
private static void BlitMarker(Minimap minimap, FieldInfo field, Color32[] output, float mapMinX, float mapMinY, float mapW, float mapH)
{
object? obj = field?.GetValue(minimap);
RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy)
{
Image component = ((Component)val).GetComponent<Image>();
if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled && (Object)(object)component.sprite != (Object)null)
{
BlitImage(output, mapMinX, mapMinY, mapW, mapH, val, component);
}
}
}
private static void BlitImage(Color32[] output, float mapMinX, float mapMinY, float mapW, float mapH, RectTransform target, Image img)
{
//IL_0135: 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_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_01ac: 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_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: 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_027c: Unknown result type (might be due to invalid IL or missing references)
//IL_028c: Unknown result type (might be due to invalid IL or missing references)
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: 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_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_0303: Unknown result type (might be due to invalid IL or missing references)
//IL_031a: Unknown result type (might be due to invalid IL or missing references)
//IL_0331: Unknown result type (might be due to invalid IL or missing references)
//IL_0348: Unknown result type (might be due to invalid IL or missing references)
//IL_034d: Unknown result type (might be due to invalid IL or missing references)
//IL_02db: Unknown result type (might be due to invalid IL or missing references)
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
Vector3[] array = (Vector3[])(object)new Vector3[4];
target.GetWorldCorners(array);
float num = (array[0].x + array[2].x) * 0.5f;
float num2 = (array[0].y + array[2].y) * 0.5f;
float num3 = array[2].x - array[0].x;
float num4 = array[2].y - array[0].y;
if (num3 <= 0f || num4 <= 0f)
{
return;
}
float num5 = (num - mapMinX) / mapW;
float num6 = (num2 - mapMinY) / mapH;
int num7 = Mathf.RoundToInt(num5 * 1920f);
int num8 = Mathf.RoundToInt(num6 * 1080f);
float num9 = 1920f / mapW;
float num10 = 1080f / mapH;
int num11 = Mathf.Max(1, Mathf.RoundToInt(num3 * num9));
int num12 = Mathf.Max(1, Mathf.RoundToInt(num4 * num10));
int num13 = num11 / 2;
int num14 = num12 / 2;
if (num7 + num13 < 0 || num7 - num13 >= 1920 || num8 + num14 < 0 || num8 - num14 >= 1080)
{
return;
}
Sprite sprite = img.sprite;
Rect textureRect = sprite.textureRect;
int num15 = Mathf.RoundToInt(((Rect)(ref textureRect)).x);
int num16 = Mathf.RoundToInt(((Rect)(ref textureRect)).y);
int num17 = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
int num18 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
if (num17 <= 0 || num18 <= 0)
{
return;
}
Color32[] array2 = ReadPixelsSafe(sprite.texture);
if (array2 == null)
{
return;
}
int width = ((Texture)sprite.texture).width;
Color32 val = Color32.op_Implicit(((Graphic)img).color);
float num19 = (float)num17 / (float)num11;
float num20 = (float)num18 / (float)num12;
for (int i = 0; i < num12; i++)
{
int num21 = num8 - num14 + i;
if (num21 < 0 || num21 >= 1080)
{
continue;
}
int num22 = Mathf.Clamp((int)((float)i * num20), 0, num18 - 1);
int num23 = (num16 + num22) * width + num15;
int num24 = num21 * 1920;
for (int j = 0; j < num11; j++)
{
int num25 = num7 - num13 + j;
if (num25 < 0 || num25 >= 1920)
{
continue;
}
int num26 = Mathf.Clamp((int)((float)j * num19), 0, num17 - 1);
Color32 val2 = array2[num23 + num26];
int num27 = val2.a * val.a / 255;
if (num27 != 0)
{
int num28 = val2.r * val.r / 255;
int num29 = val2.g * val.g / 255;
int num30 = val2.b * val.b / 255;
int num31 = num24 + num25;
if (num27 >= 250)
{
output[num31] = new Color32((byte)num28, (byte)num29, (byte)num30, byte.MaxValue);
continue;
}
Color32 val3 = output[num31];
int num32 = 255 - num27;
output[num31] = new Color32((byte)((num28 * num27 + val3.r * num32) / 255), (byte)((num29 * num27 + val3.g * num32) / 255), (byte)((num30 * num27 + val3.b * num32) / 255), byte.MaxValue);
}
}
}
}
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;
}
}
private static byte[] Encode(Color32[] output)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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: Expected O, but got Unknown
//IL_002a: Expected O, but got Unknown
Texture2D val = new Texture2D(1920, 1080, (TextureFormat)3, false);
val.SetPixels32(output);
val.Apply();
byte[] result = ImageConversion.EncodeToPNG(val);
Object.Destroy((Object)val);
return result;
}
}
internal static class MinimapButtonCaptureSuppressor
{
internal struct SavedActive
{
public GameObject Go;
public bool WasActive;
}
internal static List<SavedActive> Begin(Minimap minimap)
{
List<SavedActive> list = new List<SavedActive>();
if ((Object)(object)minimap == (Object)null || (Object)(object)minimap.m_largeRoot == (Object)null)
{
return list;
}
Button[] componentsInChildren = minimap.m_largeRoot.GetComponentsInChildren<Button>(true);
foreach (Button val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null))
{
GameObject gameObject = ((Component)val).gameObject;
list.Add(new SavedActive
{
Go = gameObject,
WasActive = gameObject.activeSelf
});
gameObject.SetActive(false);
}
}
return list;
}
internal static void End(List<SavedActive> saved)
{
if (saved == null)
{
return;
}
for (int i = 0; i < saved.Count; i++)
{
SavedActive savedActive = saved[i];
if ((Object)(object)savedActive.Go != (Object)null)
{
savedActive.Go.SetActive(savedActive.WasActive);
}
}
}
}
[HarmonyPatch]
public static class MinimapPatch
{
[HarmonyPatch(typeof(Minimap), "Start")]
[HarmonyAfter(new string[] { "ZenDragon.ZenMap" })]
[HarmonyPostfix]
private static void Minimap_Start_Postfix()
{
DiscordButton.Create();
}
[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
DiscordButton.SetVisible((int)mode == 2);
}
}
internal static class NetworkConfigSync
{
private const string RpcRequestConfig = "NMDA_RequestConfig";
private const string RpcReceiveConfig = "NMDA_ReceiveConfig";
private const int ProtocolVersion = 3;
private static bool _initialized;
private static bool _requestedFromServer;
private static Plugin.CaptureMethodMode? _serverCaptureMethod;
private static int? _serverCaptureSuperSize;
private static bool? _serverSpoilerImageData;
private static bool? _serverHideClouds;
public static bool EffectiveUseTextureCapture => (_serverCaptureMethod ?? Plugin.CaptureMethod.Value) == Plugin.CaptureMethodMode.TextureCapture;
public static int EffectiveCaptureSuperSize => _serverCaptureSuperSize ?? Plugin.CaptureSuperSize.Value;
public static bool EffectiveSpoilerImageData => _serverSpoilerImageData ?? Plugin.SpoilerImageData.Value;
public static bool EffectiveHideClouds => _serverHideClouds ?? Plugin.HideClouds.Value;
public static void Init()
{
if (!_initialized)
{
_initialized = true;
if ((Object)(object)Plugin.Instance != (Object)null)
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(RegisterWhenReady());
}
}
}
private static IEnumerator RegisterWhenReady()
{
while (ZRoutedRpc.instance == null)
{
yield return null;
}
if (TryRegisterRpc("NMDA_RequestConfig", RPC_RequestConfig) && TryRegisterRpc("NMDA_ReceiveConfig", RPC_ReceiveConfig) && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
{
RequestFromServer();
}
}
private static bool TryRegisterRpc(string name, Action<long, ZPackage> handler)
{
try
{
ZRoutedRpc.instance.Register<ZPackage>(name, handler);
return true;
}
catch (ArgumentException)
{
Debug.Log((object)("[NoMapDiscordAdditions] RPC already registered (hot-reload): " + name));
return true;
}
catch (Exception arg)
{
Debug.LogWarning((object)$"[NoMapDiscordAdditions] Failed to register RPC {name}: {arg}");
return false;
}
}
public static void Tick()
{
if (!_requestedFromServer && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && ZRoutedRpc.instance != null)
{
RequestFromServer();
}
}
private static void RequestFromServer()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
if (_requestedFromServer)
{
return;
}
_requestedFromServer = true;
long num = TryGetServerPeerId();
ZPackage val = new ZPackage();
val.Write(3);
try
{
ZRoutedRpc.instance.InvokeRoutedRPC(num, "NMDA_RequestConfig", new object[1] { val });
}
catch (Exception ex)
{
Debug.LogWarning((object)("[NoMapDiscordAdditions] Config request failed (no server override?): " + ex.Message));
}
}
private static void RPC_RequestConfig(long sender, ZPackage pkg)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
{
ZPackage val = new ZPackage();
val.Write(3);
val.Write((int)Plugin.CaptureMethod.Value);
val.Write(Plugin.CaptureSuperSize.Value);
val.Write(Plugin.SpoilerImageData.Value);
val.Write(Plugin.HideClouds.Value);
ZRoutedRpc.instance.InvokeRoutedRPC(sender, "NMDA_ReceiveConfig", new object[1] { val });
}
}
private static void RPC_ReceiveConfig(long sender, ZPackage pkg)
{
try
{
if (pkg.ReadInt() == 3)
{
int num = pkg.ReadInt();
_serverCaptureMethod = ((!Enum.IsDefined(typeof(Plugin.CaptureMethodMode), num)) ? Plugin.CaptureMethodMode.ScreenCapture : ((Plugin.CaptureMethodMode)num));
_serverCaptureSuperSize = pkg.ReadInt();
_serverSpoilerImageData = pkg.ReadBool();
_serverHideClouds = pkg.ReadBool();
Debug.Log((object)("[NoMapDiscordAdditions] Server-authoritative config applied: " + $"CaptureMethod={_serverCaptureMethod}, CaptureSuperSize={_serverCaptureSuperSize}, " + $"SpoilerImageData={_serverSpoilerImageData}, HideClouds={_serverHideClouds}"));
}
}
catch (Exception arg)
{
Debug.LogWarning((object)$"[NoMapDiscordAdditions] Failed to read server config: {arg}");
}
}
private static long TryGetServerPeerId()
{
try
{
MethodInfo method = typeof(ZRoutedRpc).GetMethod("GetServerPeerID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null && ZRoutedRpc.instance != null)
{
return (long)method.Invoke(ZRoutedRpc.instance, null);
}
}
catch
{
}
return 1L;
}
}
[BepInPlugin("com.virtualbjorn.nomapdiscordadditions", "NoMapDiscordAdditions", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public enum CaptureMethodMode
{
TextureCapture,
ScreenCapture
}
public const string PluginGUID = "com.virtualbjorn.nomapdiscordadditions";
public const string PluginName = "NoMapDiscordAdditions";
public const string PluginVersion = "1.0.0";
private const string SyncedWithServerTag = " (Synced with Server)";
public static ConfigEntry<string> WebhookUrl;
public static ConfigEntry<string> MessageTemplate;
public static ConfigEntry<int> CaptureSuperSize;
public static ConfigEntry<KeyCode> ScreenshotKey;
public static ConfigEntry<CaptureMethodMode> CaptureMethod;
public static ConfigEntry<bool> SpoilerImageData;
public static ConfigEntry<bool> HideClouds;
private Harmony _harmony;
private bool _sendingInProgress;
public static Plugin Instance { get; private set; }
private void Awake()
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Expected O, but got Unknown
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Invalid comparison between Unknown and I4
Instance = this;
WebhookUrl = ((BaseUnityPlugin)this).Config.Bind<string>("Discord", "Webhook URL", "", "Discord webhook URL used to send captured map images.");
MessageTemplate = ((BaseUnityPlugin)this).Config.Bind<string>("Discord", "Message Template", "{player} shared a map update from {biome}", "Message sent with each screenshot. Supports {player} and {biome} placeholders.");
CaptureSuperSize = ((BaseUnityPlugin)this).Config.Bind<int>("Discord", "Capture Super Size", 2, new ConfigDescription("Screen-capture quality multiplier before map crop. Higher values improve detail but increase frame-time and VRAM use. 1 = native, 2 = recommended, 3-4 = heavy. (Synced with Server)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
ScreenshotKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "Screenshot Key", (KeyCode)291, "Press while large map is open to capture and send to Discord.");
CaptureMethod = ((BaseUnityPlugin)this).Config.Bind<CaptureMethodMode>("Discord", "Capture Method", CaptureMethodMode.ScreenCapture, "Choose the map capture mode. (Synced with Server)");
SpoilerImageData = ((BaseUnityPlugin)this).Config.Bind<bool>("Discord", "Spoiler Image Data", false, "If enabled, sent map image attachments are tagged as Discord spoilers. (Synced with Server)");
HideClouds = ((BaseUnityPlugin)this).Config.Bind<bool>("Discord", "Hide Clouds", true, "If enabled, cloud overlay is suppressed while capturing maps. (Synced with Server)");
WebhookUrl.SettingChanged += delegate
{
DiscordButton.RefreshEnabledState();
};
ServerSyncCompat.Init(((BaseUnityPlugin)this).Config, "com.virtualbjorn.nomapdiscordadditions", "NoMapDiscordAdditions", "1.0.0");
if (!ServerSyncCompat.IsActive)
{
NetworkConfigSync.Init();
}
_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;
DiscordButton.Create();
DiscordButton.SetVisible(visible);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)"NoMapDiscordAdditions v1.0.0 loaded.");
}
private void Update()
{
//IL_001a: 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_003f: Invalid comparison between Unknown and I4
if (!_sendingInProgress)
{
if (!ServerSyncCompat.IsActive)
{
NetworkConfigSync.Tick();
}
if (Input.GetKeyDown(ScreenshotKey.Value) && !((Object)(object)Minimap.instance == (Object)null) && (int)Minimap.instance.m_mode == 2)
{
TriggerDiscordSend();
}
}
}
public void TriggerDiscordSend()
{
if (!_sendingInProgress && !string.IsNullOrEmpty(WebhookUrl.Value))
{
_sendingInProgress = true;
bool flag = (ServerSyncCompat.IsActive ? (CaptureMethod.Value == CaptureMethodMode.TextureCapture) : NetworkConfigSync.EffectiveUseTextureCapture);
((MonoBehaviour)this).StartCoroutine(flag ? CaptureAndSendPreferTexture() : CaptureAndSendScreen());
}
}
private IEnumerator CaptureAndSendScreen()
{
BuildCaptureContext(out var player, out var playerName, out var biome, out var message);
try
{
byte[] imageData = null;
yield return MapCapture.CaptureVisibleMap(delegate(byte[] data)
{
imageData = data;
});
yield return SendCapturedImage(imageData, player, playerName, biome, message);
}
finally
{
_sendingInProgress = false;
}
}
private IEnumerator CaptureAndSendPreferTexture()
{
BuildCaptureContext(out var player, out var playerName, out var biome, out var message);
try
{
yield return (object)new WaitForEndOfFrame();
byte[] imageData = MapCaptureTexture.CaptureMap();
if (imageData == null)
{
yield return MapCapture.CaptureVisibleMap(delegate(byte[] data)
{
imageData = data;
});
}
yield return SendCapturedImage(imageData, player, playerName, biome, message);
}
finally
{
_sendingInProgress = false;
}
}
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;
message = MessageTemplate.Value;
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;
}
string filename = BuildMapFileName(playerName, biome);
if (player != null)
{
((Character)player).Message((MessageType)2, "Sending map to Discord...", 0, (Sprite)null);
}
bool useSpoilerTag = (ServerSyncCompat.IsActive ? SpoilerImageData.Value : NetworkConfigSync.EffectiveSpoilerImageData);
yield return DiscordWebhook.SendImage(imageData, filename, message, useSpoilerTag);
}
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();
}
}
}
internal static class ServerSyncCompat
{
private static object _configSync;
private static PropertyInfo _syncedProp;
public static bool IsActive { get; private set; }
public static void Init(ConfigFile config, string modGuid, string displayName, string version)
{
if (IsActive)
{
return;
}
try
{
Type type = Type.GetType("ServerSync.ConfigSync, ServerSync");
if (!(type == null))
{
_configSync = Activator.CreateInstance(type, modGuid);
if (_configSync != null)
{
SetProp(_configSync, "DisplayName", displayName);
SetProp(_configSync, "CurrentVersion", version);
SetProp(_configSync, "MinimumRequiredVersion", version);
ConfigEntry<bool> val = config.Bind<bool>("Discord", "Lock Configuration", false, "If true, configuration can only be changed by the server/admins.");
InvokeGeneric<bool>(_configSync, "AddLockingConfigEntry", val);
AddSynced<bool>(val, synchronizedSetting: false);
AddSynced<Plugin.CaptureMethodMode>(Plugin.CaptureMethod, synchronizedSetting: true);
AddSynced<int>(Plugin.CaptureSuperSize, synchronizedSetting: true);
AddSynced<bool>(Plugin.SpoilerImageData, synchronizedSetting: true);
AddSynced<bool>(Plugin.HideClouds, synchronizedSetting: true);
IsActive = true;
Debug.Log((object)"[NoMapDiscordAdditions] ServerSync detected; using server-authoritative config sync.");
}
}
}
catch (Exception ex)
{
Debug.LogWarning((object)("[NoMapDiscordAdditions] ServerSync init failed; falling back to RPC sync. " + ex.Message));
IsActive = false;
_configSync = null;
_syncedProp = null;
}
}
private static void AddSynced<T>(ConfigEntry<T> entry, bool synchronizedSetting)
{
if (_configSync == null)
{
return;
}
object obj = InvokeGeneric<T>(_configSync, "AddConfigEntry", entry);
if (obj != null)
{
if ((object)_syncedProp == null)
{
_syncedProp = obj.GetType().GetProperty("SynchronizedConfig", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
_syncedProp?.SetValue(obj, synchronizedSetting, null);
}
}
private static void SetProp(object obj, string propName, object value)
{
obj.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, value, null);
}
private static object InvokeGeneric<T>(object obj, string methodName, ConfigEntry<T> arg)
{
MethodInfo[] methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (!(methodInfo.Name != methodName) && methodInfo.IsGenericMethodDefinition && methodInfo.GetParameters().Length == 1)
{
return methodInfo.MakeGenericMethod(typeof(T)).Invoke(obj, new object[1] { arg });
}
}
return null;
}
}
}