Decompiled source of Mountain Only Snow v1.0.3

MountainOnlySnow.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.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;
		}
	}
}
[BepInPlugin("local.valheim.mountainonlysnow", "Mountain Only Snow", "1.0.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MountainOnlySnow : BaseUnityPlugin
{
	private sealed class RendererState
	{
		internal Material[] Materials;

		internal MaterialPropertyBlock[] Original;

		internal bool Outside;
	}

	internal static MountainOnlySnow Instance;

	private Harmony harmony;

	private Coroutine scanner;

	private readonly Dictionary<Renderer, RendererState> states = new Dictionary<Renderer, RendererState>();

	private readonly List<Renderer> dead = new List<Renderer>();

	private static readonly int AddSnow = Shader.PropertyToID("_AddSnow");

	private static readonly int SnowCover = Shader.PropertyToID("_SnowCover");

	private static readonly int SnowLevel = Shader.PropertyToID("_SnowLevel");

	private static readonly FieldInfo RenderMesh = AccessTools.Field(typeof(Heightmap), "m_renderMesh");

	private bool reportedError;

	private void Awake()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_0061: 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_0075: Expected O, but got Unknown
		Instance = this;
		if (RenderMesh == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Unsupported Heightmap layout. Mountain Only Snow was not enabled.");
			return;
		}
		harmony = new Harmony("local.valheim.mountainonlysnow");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Heightmap), "RebuildRenderMesh", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MountainOnlySnow), "TerrainPostfix", (Type[])null)
		{
			priority = 0
		}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		scanner = ((MonoBehaviour)this).StartCoroutine(Scan());
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Mountain Only Snow 1.0.3 enabled. Character/equipment renderers excluded; Mountain trees and Deep North keep snow.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Built against Valheim 1.0.20 / Unity 6000 and BepInEx 5.4.23.5. Better Continents biome queries are respected.");
	}

	private static void TerrainPostfix(Heightmap __instance)
	{
		if ((Object)(object)Instance == (Object)null || WorldGenerator.instance == null)
		{
			return;
		}
		try
		{
			FixTerrain(__instance);
		}
		catch (Exception e)
		{
			Instance.Report(e);
		}
	}

	private void Report(Exception e)
	{
		if (!reportedError)
		{
			reportedError = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Snow correction failed (further repeats suppressed): " + e));
		}
	}

	internal static bool KeepsSnow(Vector3 point)
	{
		//IL_0005: 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)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return MountainTerrainMask.KeepsSnow(WorldGenerator.instance.GetBiome(point.x, point.z, 0.02f, false));
	}

	private static void FixTerrain(Heightmap heightmap)
	{
		//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)
		//IL_005b: 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_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)
		//IL_0085: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: 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_00d5: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		object? value = RenderMesh.GetValue(heightmap);
		Mesh val = (Mesh)((value is Mesh) ? value : null);
		if ((Object)(object)val == (Object)null || !val.isReadable)
		{
			return;
		}
		Vector3[] vertices = val.vertices;
		Color32[] colors = val.colors32;
		if (vertices.Length == 0 || colors.Length != vertices.Length)
		{
			return;
		}
		bool flag = false;
		for (int i = 0; i < vertices.Length; i++)
		{
			Vector3 val2 = ((Component)heightmap).transform.TransformPoint(vertices[i]);
			Biome biome = WorldGenerator.instance.GetBiome(val2.x, val2.z, 0.02f, false);
			Color32 val3 = colors[i];
			Color32 val4 = MountainTerrainMask.Filter(val3, biome);
			if (val3.r != val4.r || val3.g != val4.g || val3.b != val4.b || val3.a != val4.a)
			{
				colors[i] = val4;
				flag = true;
			}
		}
		if (flag)
		{
			val.colors32 = colors;
		}
	}

	private IEnumerator Scan()
	{
		yield return null;
		while (true)
		{
			if (WorldGenerator.instance != null)
			{
				Renderer[] renderers = Object.FindObjectsByType<Renderer>((FindObjectsSortMode)0);
				for (int i = 0; i < renderers.Length; i++)
				{
					Renderer val = renderers[i];
					if ((Object)(object)val != (Object)null)
					{
						Scene scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							try
							{
								FixRenderer(val);
							}
							catch (Exception e)
							{
								Report(e);
							}
						}
					}
					if ((i & 0x7F) == 127)
					{
						yield return null;
					}
				}
				dead.Clear();
				foreach (KeyValuePair<Renderer, RendererState> state in states)
				{
					if ((Object)(object)state.Key == (Object)null)
					{
						dead.Add(state.Key);
					}
				}
				foreach (Renderer item in dead)
				{
					states.Remove(item);
				}
			}
			yield return (object)new WaitForSeconds(2f);
		}
	}

	private void FixRenderer(Renderer renderer)
	{
		//IL_006b: 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_007c: 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_008d: 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_00b1: 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_0098: 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_009f: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Expected O, but got Unknown
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Expected O, but got Unknown
		if ((Object)(object)((Component)renderer).GetComponent<Heightmap>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<Character>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<VisEquipment>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<Ragdoll>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<ItemDrop>() != (Object)null)
		{
			return;
		}
		TreeBase componentInParent = ((Component)renderer).GetComponentInParent<TreeBase>();
		Vector3 val = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).transform.position : ((Component)renderer).transform.position);
		Biome biome = WorldGenerator.instance.GetBiome(val.x, val.z, 0.02f, false);
		if ((Object)(object)componentInParent != (Object)null)
		{
			Biome val2 = Heightmap.FindBiome(val);
			if ((int)val2 != 0)
			{
				biome = val2;
			}
		}
		bool flag = !MountainTerrainMask.KeepsSnow(biome);
		bool flag2 = MountainTerrainMask.ForceTreeSnow(biome, (Object)(object)componentInParent != (Object)null);
		if (!states.TryGetValue(renderer, out var value))
		{
			Material[] sharedMaterials = renderer.sharedMaterials;
			bool flag3 = false;
			Material[] array = sharedMaterials;
			foreach (Material val3 in array)
			{
				if ((Object)(object)val3 != (Object)null && (val3.HasProperty(AddSnow) || val3.HasProperty(SnowCover) || val3.HasProperty(SnowLevel)))
				{
					flag3 = true;
				}
			}
			if (!flag3)
			{
				return;
			}
			value = new RendererState
			{
				Materials = sharedMaterials,
				Original = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[sharedMaterials.Length]
			};
			for (int j = 0; j < sharedMaterials.Length; j++)
			{
				value.Original[j] = new MaterialPropertyBlock();
				renderer.GetPropertyBlock(value.Original[j], j);
			}
			states.Add(renderer, value);
		}
		if (!flag && !flag2)
		{
			if (value.Outside)
			{
				for (int k = 0; k < value.Materials.Length; k++)
				{
					renderer.SetPropertyBlock(value.Original[k], k);
				}
			}
			value.Outside = false;
			return;
		}
		MaterialPropertyBlock val4 = new MaterialPropertyBlock();
		for (int l = 0; l < value.Materials.Length; l++)
		{
			Material val5 = value.Materials[l];
			if (!((Object)(object)val5 == (Object)null) && (val5.HasProperty(AddSnow) || val5.HasProperty(SnowCover) || val5.HasProperty(SnowLevel)))
			{
				renderer.GetPropertyBlock(val4, l);
				if (val4.isEmpty)
				{
					renderer.GetPropertyBlock(val4);
				}
				float num = (flag2 ? 1f : 0f);
				if (val5.HasProperty(AddSnow))
				{
					val4.SetFloat(AddSnow, num);
				}
				if (val5.HasProperty(SnowCover))
				{
					val4.SetFloat(SnowCover, num);
				}
				if (val5.HasProperty(SnowLevel))
				{
					val4.SetFloat(SnowLevel, num);
				}
				renderer.SetPropertyBlock(val4, l);
				val4.Clear();
			}
		}
		value.Outside = true;
	}

	private void OnDestroy()
	{
		if (scanner != null)
		{
			((MonoBehaviour)this).StopCoroutine(scanner);
		}
		foreach (KeyValuePair<Renderer, RendererState> state in states)
		{
			if ((Object)(object)state.Key != (Object)null && state.Value.Outside)
			{
				for (int i = 0; i < state.Value.Original.Length; i++)
				{
					state.Key.SetPropertyBlock(state.Value.Original[i], i);
				}
			}
		}
		states.Clear();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}
}
public static class MountainTerrainMask
{
	public static bool ForceTreeSnow(Biome biome, bool isTree)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Invalid comparison between Unknown and I4
		if (isTree)
		{
			return (int)biome == 4;
		}
		return false;
	}

	public static bool KeepsSnow(Biome biome)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		if ((int)biome != 4)
		{
			return (int)biome == 64;
		}
		return true;
	}

	public static Color32 Filter(Color32 before, Biome biome)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Invalid comparison between Unknown and I4
		//IL_0005: 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_000b: 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_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)
		if ((int)biome == 64)
		{
			return before;
		}
		if ((int)biome != 4)
		{
			return new Color32(before.r, (byte)0, before.b, before.a);
		}
		return new Color32((byte)0, byte.MaxValue, (byte)0, (byte)0);
	}
}