Decompiled source of MapFogCleaner v1.1.1

MapFogCleaner.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MapFogCleaner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("MapFogCleaner")]
[assembly: AssemblyTitle("MapFogCleaner")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MapFogCleaner
{
	public class CloudShadowToggleController : MonoBehaviour
	{
		private static readonly FieldRef<Minimap, Material> MapLargeShaderRef = AccessTools.FieldRefAccess<Minimap, Material>("m_mapLargeShader");

		private static readonly FieldRef<Minimap, Material> MapSmallShaderRef = AccessTools.FieldRefAccess<Minimap, Material>("m_mapSmallShader");

		private static Texture2D _transparentTex;

		private Material _large;

		private Material _small;

		private Texture _origLargeCloud;

		private Texture _origSmallCloud;

		private bool _hiddenApplied;

		private void Update()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_large == (Object)null || (Object)(object)_small == (Object)null)
			{
				Minimap instance = Minimap.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				Material val = MapLargeShaderRef.Invoke(instance);
				Material val2 = MapSmallShaderRef.Invoke(instance);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return;
				}
				_large = val;
				_small = val2;
				_origLargeCloud = _large.GetTexture("_CloudTex");
				_origSmallCloud = _small.GetTexture("_CloudTex");
				MapFogCleanerPlugin.LogStatic("CloudShadowToggle: map materials captured.");
			}
			bool value = MapFogCleanerPlugin.HideCloudShadows.Value;
			if (value == _hiddenApplied)
			{
				return;
			}
			if (value)
			{
				if ((Object)(object)_transparentTex == (Object)null)
				{
					_transparentTex = new Texture2D(1, 1, (TextureFormat)4, false);
					_transparentTex.SetPixel(0, 0, new Color(0f, 0f, 0f, 0f));
					_transparentTex.Apply();
				}
				_large.SetTexture("_CloudTex", (Texture)(object)_transparentTex);
				_small.SetTexture("_CloudTex", (Texture)(object)_transparentTex);
			}
			else
			{
				_large.SetTexture("_CloudTex", _origLargeCloud);
				_small.SetTexture("_CloudTex", _origSmallCloud);
			}
			_hiddenApplied = value;
			MapFogCleanerPlugin.LogStatic($"CloudShadowToggle: hidden={value}");
		}
	}
	[HarmonyPatch(typeof(Minimap), "Awake")]
	internal static class Minimap_Awake_AddCloudToggle
	{
		private static void Postfix(Minimap __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<CloudShadowToggleController>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<CloudShadowToggleController>();
			}
		}
	}
	public class FogCleanerController : MonoBehaviour
	{
		private static readonly FieldRef<Minimap, bool[]> ExploredRef = AccessTools.FieldRefAccess<Minimap, bool[]>("m_explored");

		private static readonly FieldRef<Minimap, Texture2D> FogTextureRef = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture");

		private const int StepsPerFrame = 20000;

		private bool[] _explored;

		private Texture2D _fogTexture;

		private int _textureSize;

		private float _pixelSize;

		private bool _ready;

		private float _timer;

		private Coroutine _scanCoroutine;

		private void Update()
		{
			if (!MapFogCleanerPlugin.Enabled.Value || (!_ready && !TryCapture()))
			{
				return;
			}
			_timer -= Time.deltaTime;
			if (!(_timer > 0f))
			{
				_timer = MapFogCleanerPlugin.ScanInterval.Value;
				if (_scanCoroutine == null)
				{
					_scanCoroutine = ((MonoBehaviour)this).StartCoroutine(ScanAndFillRoutine());
				}
			}
		}

		private bool TryCapture()
		{
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			bool[] array = ExploredRef.Invoke(instance);
			Texture2D val = FogTextureRef.Invoke(instance);
			if (array == null || (Object)(object)val == (Object)null || instance.m_textureSize <= 0)
			{
				return false;
			}
			_explored = array;
			_fogTexture = val;
			_textureSize = instance.m_textureSize;
			_pixelSize = instance.m_pixelSize;
			_ready = true;
			int num = 0;
			bool[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (array2[i])
				{
					num++;
				}
			}
			MapFogCleanerPlugin.LogStatic($"Ready: explored.Length={array.Length}, textureSize={_textureSize}, pixelSize={_pixelSize}, exploredCount={num}");
			return true;
		}

		private IEnumerator ScanAndFillRoutine()
		{
			int size = _textureSize;
			float num = MapFogCleanerPlugin.MaxIslandRadius.Value / _pixelSize;
			int maxIslandSize = Mathf.Max(1, Mathf.RoundToInt((float)Math.PI * num * num));
			bool[] visited = new bool[size * size];
			List<int> pending = new List<int>(64);
			Queue<int> queue = new Queue<int>();
			bool changed = false;
			int componentsChecked = 0;
			int islandsFilled = 0;
			int cellsFilled = 0;
			int largestSkipped = 0;
			int steps = 0;
			for (int start = 0; start < size * size; start++)
			{
				int num2 = steps + 1;
				steps = num2;
				if (num2 >= 20000)
				{
					steps = 0;
					yield return null;
				}
				if (visited[start] || _explored[start])
				{
					continue;
				}
				pending.Clear();
				queue.Clear();
				queue.Enqueue(start);
				visited[start] = true;
				int componentSize = 0;
				while (queue.Count > 0)
				{
					num2 = steps + 1;
					steps = num2;
					if (num2 >= 20000)
					{
						steps = 0;
						yield return null;
					}
					int num3 = queue.Dequeue();
					componentSize++;
					if (pending.Count <= maxIslandSize)
					{
						pending.Add(num3);
					}
					int num4 = num3 % size;
					int num5 = num3 / size;
					TryEnqueue(num4 - 1, num5, size, visited, queue, _explored);
					TryEnqueue(num4 + 1, num5, size, visited, queue, _explored);
					TryEnqueue(num4, num5 - 1, size, visited, queue, _explored);
					TryEnqueue(num4, num5 + 1, size, visited, queue, _explored);
				}
				componentsChecked++;
				if (componentSize <= maxIslandSize)
				{
					islandsFilled++;
					foreach (int item in pending)
					{
						if (Explore(item % size, item / size, size))
						{
							changed = true;
							cellsFilled++;
						}
					}
				}
				else if (componentSize > largestSkipped)
				{
					largestSkipped = componentSize;
				}
			}
			if (changed)
			{
				_fogTexture.Apply();
			}
			MapFogCleanerPlugin.LogStatic($"ScanAndFill: maxIslandCells={maxIslandSize}, componentsChecked={componentsChecked}, islandsFilled={islandsFilled}, cellsFilled={cellsFilled}, largestSkipped={largestSkipped}, changed={changed}");
			_scanCoroutine = null;
		}

		private static void TryEnqueue(int x, int y, int size, bool[] visited, Queue<int> queue, bool[] explored)
		{
			if (x >= 0 && x < size && y >= 0 && y < size)
			{
				int num = y * size + x;
				if (!visited[num] && !explored[num])
				{
					visited[num] = true;
					queue.Enqueue(num);
				}
			}
		}

		private bool Explore(int x, int y, int size)
		{
			//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_0034: Unknown result type (might be due to invalid IL or missing references)
			int num = y * size + x;
			if (_explored[num])
			{
				return false;
			}
			Color pixel = _fogTexture.GetPixel(x, y);
			pixel.r = 0f;
			_fogTexture.SetPixel(x, y, pixel);
			_explored[num] = true;
			return true;
		}
	}
	[HarmonyPatch(typeof(Minimap), "Awake")]
	internal static class Minimap_Awake_AddFogCleaner
	{
		private static void Postfix(Minimap __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<FogCleanerController>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<FogCleanerController>();
			}
		}
	}
	[BepInPlugin("sopmehua.valheim.mapfogcleaner", "MapFogCleaner", "1.1.1")]
	public class MapFogCleanerPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "sopmehua.valheim.mapfogcleaner";

		public const string PluginName = "MapFogCleaner";

		public const string PluginVersion = "1.1.1";

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> MaxIslandRadius;

		public static ConfigEntry<float> ScanInterval;

		public static ConfigEntry<bool> HideCloudShadows;

		private static ManualLogSource _log;

		private Harmony _harmony;

		internal static void LogStatic(string message)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			_log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Включить/выключить мод.");
			MaxIslandRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxIslandRadius", 100f, new ConfigDescription("Максимальный размер (примерный радиус в игровых метрах, не в клетках текстуры — разные миры могут использовать разное разрешение сетки тумана) неоткрытого 'островка', окружённого исследованной территорией, который будет автоматически закрашен. Больше значение — закрашиваются более крупные пятна тумана.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 2000f), Array.Empty<object>()));
			ScanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScanInterval", 4f, new ConfigDescription("Как часто (в секундах) проверять карту на маленькие пятна тумана.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			HideCloudShadows = ((BaseUnityPlugin)this).Config.Bind<bool>("Map", "HideCloudShadows", false, "Убрать плывущие тени облаков на большой карте и на миникарте. Только визуально, на туман войны/исследование не влияет.");
			_harmony = new Harmony("sopmehua.valheim.mapfogcleaner");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MapFogCleaner 1.1.1 загружен.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}