Decompiled source of ValheimZoneGrid v0.8.0

BepInEx/plugins/Zonegrid.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Zonegrid")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Zonegrid")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b4a0a4df-039b-49f2-ae18-866afc596fa2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ValheimZoneGrid;

[BepInPlugin("se.dunderlan.valheimzonegrid", "Valheim Zone Grid", "0.8.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ZoneGrid : BaseUnityPlugin
{
	private sealed class MapLines
	{
		private readonly RawImage mapImage;

		private readonly RectTransform root;

		private readonly List<Image> vertical = new List<Image>();

		private readonly List<Image> horizontal = new List<Image>();

		internal MapLines(RawImage image, string objectName)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0073: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			mapImage = image;
			GameObject val = new GameObject(objectName, new Type[2]
			{
				typeof(RectTransform),
				typeof(RectMask2D)
			});
			root = (RectTransform)val.transform;
			((Transform)root).SetParent((Transform)(object)((Graphic)image).rectTransform, false);
			root.anchorMin = Vector2.zero;
			root.anchorMax = Vector2.one;
			root.offsetMin = Vector2.zero;
			root.offsetMax = Vector2.zero;
			((Transform)root).localScale = Vector3.one;
			((Transform)root).SetAsLastSibling();
		}

		internal void Refresh(bool enabled, Color color, int mapPixels, float widthScale, float worldLength, int textureSize)
		{
			//IL_005d: 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_006e: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null || (Object)(object)mapImage == (Object)null)
			{
				return;
			}
			if (((Component)root).gameObject.activeSelf != enabled)
			{
				((Component)root).gameObject.SetActive(enabled);
			}
			if (enabled && ((Component)mapImage).gameObject.activeInHierarchy)
			{
				Rect uvRect = mapImage.uvRect;
				Rect rect = root.rect;
				if (!(Mathf.Abs(((Rect)(ref uvRect)).width) < 1E-06f) && !(Mathf.Abs(((Rect)(ref uvRect)).height) < 1E-06f) && !(((Rect)(ref rect)).width < 1f) && !(((Rect)(ref rect)).height < 1f))
				{
					float thickness = (float)mapPixels * widthScale * ((Rect)(ref rect)).width / (Mathf.Abs(((Rect)(ref uvRect)).width) * (float)textureSize);
					float thickness2 = (float)mapPixels * widthScale * ((Rect)(ref rect)).height / (Mathf.Abs(((Rect)(ref uvRect)).height) * (float)textureSize);
					int count = DrawAxis(vertical, isVertical: true, ((Rect)(ref uvRect)).xMin, ((Rect)(ref uvRect)).xMax, ((Rect)(ref rect)).width, worldLength, thickness, color);
					int count2 = DrawAxis(horizontal, isVertical: false, ((Rect)(ref uvRect)).yMin, ((Rect)(ref uvRect)).yMax, ((Rect)(ref rect)).height, worldLength, thickness2, color);
					HideUnused(vertical, count);
					HideUnused(horizontal, count2);
				}
			}
		}

		private int DrawAxis(List<Image> lines, bool isVertical, float minUv, float maxUv, float extent, float worldLength, float thickness, Color color)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0110: 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_00ed: 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)
			float num = (minUv - 0.5f) * worldLength;
			float num2 = (maxUv - 0.5f) * worldLength;
			float num3 = Mathf.Min(num, num2);
			float num4 = Mathf.Max(num, num2);
			int num5 = Mathf.CeilToInt((num3 - 32f) / 64f);
			int num6 = Mathf.FloorToInt((num4 - 32f) / 64f);
			int num7 = Mathf.Min(Mathf.Max(0, num6 - num5 + 1), 600);
			for (int i = 0; i < num7; i++)
			{
				float num8 = 32f + (float)(num5 + i) * 64f;
				float num9 = ((0.5f + num8 / worldLength - minUv) / (maxUv - minUv) - 0.5f) * extent;
				Image line = GetLine(lines, i, isVertical);
				RectTransform rectTransform = ((Graphic)line).rectTransform;
				rectTransform.anchoredPosition = (isVertical ? new Vector2(num9, 0f) : new Vector2(0f, num9));
				Rect rect;
				Vector2 sizeDelta;
				if (!isVertical)
				{
					rect = root.rect;
					sizeDelta = new Vector2(((Rect)(ref rect)).width + 2f, thickness);
				}
				else
				{
					rect = root.rect;
					sizeDelta = new Vector2(thickness, ((Rect)(ref rect)).height + 2f);
				}
				rectTransform.sizeDelta = sizeDelta;
				((Graphic)line).color = color;
				if (!((Component)line).gameObject.activeSelf)
				{
					((Component)line).gameObject.SetActive(true);
				}
			}
			return num7;
		}

		private Image GetLine(List<Image> pool, int index, bool isVertical)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0076: 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)
			if (index < pool.Count)
			{
				return pool[index];
			}
			GameObject val = new GameObject(isVertical ? "VerticalZoneBoundary" : "HorizontalZoneBoundary", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)root, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			Image component = val.GetComponent<Image>();
			((Graphic)component).raycastTarget = false;
			pool.Add(component);
			return component;
		}

		private static void HideUnused(List<Image> pool, int count)
		{
			for (int i = count; i < pool.Count; i++)
			{
				if ((Object)(object)pool[i] != (Object)null && ((Component)pool[i]).gameObject.activeSelf)
				{
					((Component)pool[i]).gameObject.SetActive(false);
				}
			}
		}

		internal void Dispose()
		{
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)root).gameObject);
			}
		}
	}

	private const float ZoneSize = 64f;

	private const float FirstBorder = 32f;

	private const int MaxLinesPerDirection = 600;

	private ConfigEntry<bool> showGrid;

	private ConfigEntry<KeyCode> toggleKey;

	private ConfigEntry<Color> gridColor;

	private ConfigEntry<int> lineWidth;

	private ConfigEntry<float> lineWidthScale;

	private Minimap currentMap;

	private MapLines fullMapLines;

	private MapLines miniMapLines;

	private static readonly FieldInfo TextureSizeField = typeof(Minimap).GetField("m_textureSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PixelSizeField = typeof(Minimap).GetField("m_pixelSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private void Awake()
	{
		//IL_006b: 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_00ac: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		showGrid = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowGrid", true, "Show the zone grid on both maps.");
		toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)289, "Toggle grid visibility.");
		gridColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Appearance", "GridColor", new Color(1f, 1f, 1f, 0.45f), "Grid line color and alpha; updates live.");
		lineWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Appearance", "LineWidthPixels", 1, new ConfigDescription("Base line thickness in Valheim map texture pixels, multiplied by LineWidthScale; updates live.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
		lineWidthScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "LineWidthScale", 0.35f, new ConfigDescription("Scale line thickness relative to one Valheim map-texture pixel. Try 0.25 to 0.5 to match visible terrain pixels; updates live.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
		if (TextureSizeField == null || PixelSizeField == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Valheim Minimap texture/pixel size fields. Grid cannot align to world coordinates.");
		}
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (Input.GetKeyDown(toggleKey.Value))
		{
			showGrid.Value = !showGrid.Value;
		}
	}

	private void LateUpdate()
	{
		//IL_011d: 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)
		Minimap instance = Minimap.instance;
		if ((Object)(object)instance == (Object)null)
		{
			DestroyViews();
		}
		else
		{
			if (TextureSizeField == null || PixelSizeField == null)
			{
				return;
			}
			if ((Object)(object)currentMap != (Object)(object)instance)
			{
				DestroyViews();
				currentMap = instance;
			}
			if (fullMapLines == null && (Object)(object)instance.m_mapImageLarge != (Object)null)
			{
				fullMapLines = new MapLines(instance.m_mapImageLarge, "ZoneGrid_Full");
			}
			if (miniMapLines == null && (Object)(object)instance.m_mapImageSmall != (Object)null)
			{
				miniMapLines = new MapLines(instance.m_mapImageSmall, "ZoneGrid_Mini");
			}
			int num;
			float num2;
			try
			{
				num = Convert.ToInt32(TextureSizeField.GetValue(instance));
				num2 = Convert.ToSingle(PixelSizeField.GetValue(instance));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to read Valheim map scale: " + ex.Message));
				return;
			}
			if (num > 0 && !(num2 <= 0f))
			{
				float worldLength = (float)num * num2;
				if (fullMapLines != null)
				{
					fullMapLines.Refresh(showGrid.Value, gridColor.Value, lineWidth.Value, lineWidthScale.Value, worldLength, num);
				}
				if (miniMapLines != null)
				{
					miniMapLines.Refresh(showGrid.Value, gridColor.Value, lineWidth.Value, lineWidthScale.Value, worldLength, num);
				}
			}
		}
	}

	private void DestroyViews()
	{
		if (fullMapLines != null)
		{
			fullMapLines.Dispose();
		}
		if (miniMapLines != null)
		{
			miniMapLines.Dispose();
		}
		fullMapLines = null;
		miniMapLines = null;
		currentMap = null;
	}

	private void OnDestroy()
	{
		DestroyViews();
	}
}