Decompiled source of VisorLite v1.1.0

VisorLite.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VisorLite")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+3b6a95af783d2a7f88cf9dccf63bf787bfcb7f7d")]
[assembly: AssemblyProduct("VisorLite")]
[assembly: AssemblyTitle("VisorLite")]
[assembly: AssemblyVersion("1.1.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;
		}
	}
}
namespace VisorLite
{
	[BepInPlugin("visorlite", "VisorLite", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public enum LayerMode
		{
			Unlit,
			Original,
			Hidden
		}

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<Key> ToggleKey;

		internal static ConfigEntry<float> GlassBrightness;

		internal static ConfigEntry<float> CondensationBrightness;

		internal static ConfigEntry<bool> SyncWithGame;

		internal static ConfigEntry<LayerMode> GlassMode;

		internal static ConfigEntry<LayerMode> CondensationMode;

		internal static bool RuntimeOn;

		private void Awake()
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<Key>("General", "ToggleKey", (Key)94, "Switch between the cheap and the original visor in game. None = no key.");
			GlassBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "GlassBrightness", 0.15f, "Colour multiplier of the unlit visor glass.");
			CondensationBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "CondensationBrightness", 0.03f, "Colour multiplier of the unlit (additive) condensation layer.");
			SyncWithGame = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "SyncCondensationWithGame", true, "Copy the game's live visor effects (condensation in rain / water) onto the cheap layers. Off = the cheap visor never changes.");
			GlassMode = ((BaseUnityPlugin)this).Config.Bind<LayerMode>("Layers", "GlassMode", LayerMode.Unlit, "Unlit = cheap copy (the speed-up), Original = keep the game's expensive glass, Hidden = don't draw it.");
			CondensationMode = ((BaseUnityPlugin)this).Config.Bind<LayerMode>("Layers", "CondensationMode", LayerMode.Unlit, "Unlit = cheap copy (the speed-up), Original = keep the game's expensive condensation (correct rain look, slower), Hidden = don't draw it.");
			RuntimeOn = Enabled.Value;
			GameObject val = new GameObject("VisorLite")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<VisorSwapper>();
			Log.LogInfo((object)string.Format("VisorLite loaded ({0}, toggle: {1})", RuntimeOn ? "enabled" : "disabled", ToggleKey.Value));
		}
	}
	internal class VisorSwapper : MonoBehaviour
	{
		private class Swap
		{
			public Renderer R;

			public Material[] Original;

			public Material[] Cheap;

			public List<(Material src, Material copy, bool additive)> Pairs = new List<(Material, Material, bool)>();
		}

		private static readonly string[] BlendProps = new string[17]
		{
			"_SurfaceType", "_BlendMode", "_SrcBlend", "_DstBlend", "_AlphaSrcBlend", "_AlphaDstBlend", "_ZWrite", "_TransparentZWrite", "_ZTestTransparent", "_CullMode",
			"_CullModeForward", "_TransparentCullMode", "_DoubleSidedEnable", "_EnableBlendModePreserveSpecularLighting", "_AlphaCutoffEnable", "_StencilRef", "_StencilWriteMask"
		};

		private readonly List<Swap> _swaps = new List<Swap>();

		private Material _template;

		private float _nextScan;

		private bool _applied;

		private bool _warned;

		private string _modes;

		private float _nextFullScan;

		private void LateUpdate()
		{
			//IL_000b: 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_0014: 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)
			Keyboard current = Keyboard.current;
			Key value = Plugin.ToggleKey.Value;
			if (current != null && (int)value != 0 && ((ButtonControl)current[value]).wasPressedThisFrame)
			{
				Plugin.RuntimeOn = !Plugin.RuntimeOn;
				Plugin.Log.LogInfo((object)("VisorLite " + (Plugin.RuntimeOn ? "ON" : "OFF")));
				try
				{
					ShowTip(Plugin.RuntimeOn ? "ON" : "OFF");
				}
				catch
				{
				}
			}
			_swaps.RemoveAll((Swap s) => (Object)(object)s.R == (Object)null);
			if (Time.unscaledTime >= _nextScan)
			{
				_nextScan = Time.unscaledTime + 2f;
				Scan();
			}
			bool runtimeOn = Plugin.RuntimeOn;
			if (runtimeOn != _applied)
			{
				foreach (Swap swap in _swaps)
				{
					swap.R.sharedMaterials = (runtimeOn ? swap.Cheap : swap.Original);
				}
				_applied = runtimeOn;
			}
			string text = $"{Plugin.GlassMode.Value}|{Plugin.CondensationMode.Value}";
			if (text != _modes)
			{
				_modes = text;
				foreach (Swap swap2 in _swaps)
				{
					BuildCheap(swap2);
					if (_applied)
					{
						swap2.R.sharedMaterials = swap2.Cheap;
					}
				}
			}
			if (!_applied || !Plugin.SyncWithGame.Value)
			{
				return;
			}
			float value2 = Plugin.GlassBrightness.Value;
			float value3 = Plugin.CondensationBrightness.Value;
			foreach (Swap swap3 in _swaps)
			{
				if (!SameMaterials(swap3.R.sharedMaterials, swap3.Cheap))
				{
					swap3.Original = swap3.R.sharedMaterials;
					BuildCheap(swap3);
					swap3.R.sharedMaterials = swap3.Cheap;
				}
				foreach (var (val, val2, flag) in swap3.Pairs)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
					{
						SetColor(val2, val, flag ? value3 : value2);
					}
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ShowTip(string body)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("VisorLite", body, false, false, "LC_Tip1");
			}
		}

		private static bool SameMaterials(Material[] a, Material[] b)
		{
			if (a == null || b == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				if (a[i] != b[i])
				{
					return false;
				}
			}
			return true;
		}

		private void Scan()
		{
			if ((Object)(object)_template == (Object)null)
			{
				_template = (from m in Resources.FindObjectsOfTypeAll<Material>()
					where (Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null && ((Object)m.shader).name == "HDRP/Unlit" && m.HasProperty("_SurfaceType") && m.GetFloat("_SurfaceType") == 1f && !((Object)m).name.Contains("VisorLite")
					select m).OrderBy(TemplateScore).FirstOrDefault();
				if ((Object)(object)_template == (Object)null)
				{
					if (!_warned)
					{
						_warned = true;
						Plugin.Log.LogWarning((object)"No transparent HDRP/Unlit material loaded yet, will retry");
					}
					return;
				}
				Plugin.Log.LogInfo((object)("Using '" + ((Object)_template).name + "' as unlit template"));
			}
			GameObject val = GameObject.Find("PlayerHUDHelmetModel");
			IEnumerable<Renderer> enumerable;
			if ((Object)(object)val != (Object)null)
			{
				enumerable = val.GetComponentsInChildren<Renderer>(true);
			}
			else
			{
				if (Time.unscaledTime < _nextFullScan)
				{
					return;
				}
				_nextFullScan = Time.unscaledTime + 10f;
				enumerable = from val2 in Object.FindObjectsOfType<Renderer>()
					where InHelmet(((Component)val2).transform)
					select val2;
			}
			foreach (Renderer r in enumerable)
			{
				if (!_swaps.Any((Swap s) => (Object)(object)s.R == (Object)(object)r) && r.sharedMaterials.Any((Material m) => (Object)(object)m != (Object)null && m.renderQueue >= 2501 && ((Object)m.shader).name == "HDRP/Lit"))
				{
					Swap swap = new Swap
					{
						R = r,
						Original = r.sharedMaterials
					};
					BuildCheap(swap);
					_swaps.Add(swap);
					if (_applied)
					{
						r.sharedMaterials = swap.Cheap;
					}
					Plugin.Log.LogInfo((object)("Visor layer found: " + ((Object)r).name + " (" + string.Join(", ", swap.Pairs.Select(((Material src, Material copy, bool additive) p) => ((Object)p.src).name)) + ")"));
				}
			}
		}

		private void BuildCheap(Swap s)
		{
			//IL_00be: 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_00db: Expected O, but got Unknown
			//IL_0124: 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)
			s.Pairs.Clear();
			s.Cheap = (Material[])(object)new Material[s.Original.Length];
			for (int i = 0; i < s.Original.Length; i++)
			{
				Material val = s.Original[i];
				if ((Object)(object)val == (Object)null || val.renderQueue < 2501 || ((Object)val.shader).name != "HDRP/Lit")
				{
					s.Cheap[i] = val;
					continue;
				}
				bool flag = val.HasProperty("_BlendMode") && val.GetFloat("_BlendMode") == 1f;
				Plugin.LayerMode layerMode = (flag ? Plugin.CondensationMode.Value : Plugin.GlassMode.Value);
				if (layerMode == Plugin.LayerMode.Original)
				{
					s.Cheap[i] = val;
					continue;
				}
				Material val2 = new Material(_template)
				{
					name = ((Object)val).name + " (VisorLite)"
				};
				Neutralize(val2);
				Texture val3 = (val.HasProperty("_BaseColorMap") ? val.GetTexture("_BaseColorMap") : null);
				val2.SetTexture("_UnlitColorMap", val3);
				if ((Object)(object)val3 != (Object)null)
				{
					val2.SetTextureScale("_UnlitColorMap", val.GetTextureScale("_BaseColorMap"));
				}
				string[] blendProps = BlendProps;
				foreach (string text in blendProps)
				{
					if (val.HasProperty(text) && val2.HasProperty(text))
					{
						val2.SetFloat(text, val.GetFloat(text));
					}
				}
				val2.renderQueue = val.renderQueue;
				if (layerMode == Plugin.LayerMode.Hidden)
				{
					val2.SetColor("_UnlitColor", new Color(0f, 0f, 0f, 0f));
					s.Cheap[i] = val2;
				}
				else
				{
					SetColor(val2, val, flag ? Plugin.CondensationBrightness.Value : Plugin.GlassBrightness.Value);
					s.Pairs.Add((val, val2, flag));
					s.Cheap[i] = val2;
				}
			}
		}

		private static void SetColor(Material copy, Material src, float k)
		{
			//IL_0006: 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_001a: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Color color = src.GetColor("_BaseColor");
			copy.SetColor("_UnlitColor", new Color(color.r * k, color.g * k, color.b * k, color.a));
		}

		private static void Neutralize(Material m)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (m.HasProperty("_EmissiveColor"))
			{
				m.SetColor("_EmissiveColor", Color.black);
			}
			if (m.HasProperty("_EmissiveColorLDR"))
			{
				m.SetColor("_EmissiveColorLDR", Color.black);
			}
			if (m.HasProperty("_EmissiveIntensity"))
			{
				m.SetFloat("_EmissiveIntensity", 0f);
			}
			if (m.HasProperty("_EmissiveColorMap"))
			{
				m.SetTexture("_EmissiveColorMap", (Texture)null);
			}
			m.DisableKeyword("_EMISSIVE_COLOR_MAP");
			if (m.HasProperty("_DistortionEnable"))
			{
				m.SetFloat("_DistortionEnable", 0f);
			}
			if (m.HasProperty("_DistortionOnly"))
			{
				m.SetFloat("_DistortionOnly", 0f);
			}
			m.DisableKeyword("_DISTORTION");
			if (m.HasProperty("_AlphaCutoffEnable"))
			{
				m.SetFloat("_AlphaCutoffEnable", 0f);
			}
			m.DisableKeyword("_ALPHATEST_ON");
		}

		private static float TemplateScore(Material m)
		{
			//IL_0019: 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_0020: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			if (m.HasProperty("_EmissiveColor"))
			{
				Color color = m.GetColor("_EmissiveColor");
				num += color.r + color.g + color.b;
			}
			if (m.HasProperty("_EmissiveColorMap") && (Object)(object)m.GetTexture("_EmissiveColorMap") != (Object)null)
			{
				num += 10f;
			}
			if (m.IsKeywordEnabled("_EMISSIVE_COLOR_MAP"))
			{
				num += 10f;
			}
			if (m.HasProperty("_DistortionEnable") && m.GetFloat("_DistortionEnable") > 0f)
			{
				num += 10f;
			}
			if (((Object)m).name.IndexOf("flame", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				num += 5f;
			}
			return num;
		}

		private static bool InHelmet(Transform t)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (((Object)t).name == "PlayerHUDHelmetModel")
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}
	}
}