Decompiled source of BetterFog v0.2.0

BetterFog/BetterFog.dll

Decompiled 2 hours ago
using System;
using System.Diagnostics;
using System.IO;
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;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterFog")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a2dcc14e9b316bf1c84754c8dd8ac83398b060ee")]
[assembly: AssemblyProduct("BetterFog")]
[assembly: AssemblyTitle("BetterFog")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BetterFog
{
	[BepInPlugin("carnuke.betterfog", "BetterFog", "0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "carnuke.betterfog";

		public const string PluginName = "BetterFog";

		public const string PluginVersion = "0.2.0";

		internal static ManualLogSource Log = null;

		private static ConfigEntry<bool> _enableBetterFog = null;

		private static ConfigEntry<float> _fogStartOverride = null;

		private static ConfigEntry<float> _fogEndOverride = null;

		private static ConfigEntry<float> _shopFogStartOverride = null;

		private static ConfigEntry<float> _shopFogEndOverride = null;

		private static FieldInfo? _lgInstanceField;

		private static FieldInfo? _lgGeneratedField;

		private static FieldInfo? _envFogColorField;

		private static FieldInfo? _envFogStartField;

		private static FieldInfo? _envFogEndField;

		private static FieldInfo? _envMainCameraField;

		private static FieldInfo? _envSetupDoneField;

		private static FieldInfo? _rmInstanceField;

		private static FieldInfo? _rmLevelCurrentField;

		private static FieldInfo? _rmLevelMainMenuField;

		private static FieldInfo? _rmLevelLobbyMenuField;

		private static FieldInfo? _rmLevelSplashScreenField;

		private static FieldInfo? _rmLevelIsShopField;

		private const float ClipPadding = 30f;

		private static Material? _fogMaterial;

		private static CylindricalFogEffect? _fogEffect;

		private const float MenuFarClipPlane = 5000f;

		private static float _desiredFarClip = 5000f;

		private static int _lastPostfixFrame = -9999;

		private static Object? _cachedEnvInstance;

		private void Awake()
		{
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"BetterFog v0.2.0 loaded.");
			_enableBetterFog = ((BaseUnityPlugin)this).Config.Bind<bool>("Fog", "Enable Better Fog", true, "Use BetterFog's radial fog instead of REPO's original fog.");
			_fogStartOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Fog", "Start Distance", 8f, "Fog start distance in world units. One level module is 15 units long. Default: 8.");
			_fogEndOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Fog", "End Distance", 16f, "Fog end distance in world units. One level module is 15 units long. Default: 16.");
			_shopFogStartOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Fog", "Shop Start Distance", 60f, "Fog start distance in shop levels. Default: 60.");
			_shopFogEndOverride = ((BaseUnityPlugin)this).Config.Bind<float>("Fog", "Shop End Distance", 300f, "Fog end distance in shop levels. Default: 300.");
			CacheReflection();
			LoadFogBundle();
			Type type = AccessTools.TypeByName("EnvironmentDirector");
			if (type == null)
			{
				Log.LogError((object)"EnvironmentDirector type not found.");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "FogLogic", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Log.LogError((object)"EnvironmentDirector.FogLogic not found.");
				return;
			}
			new Harmony("carnuke.betterfog").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "FogLogic_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log.LogInfo((object)"Patched EnvironmentDirector.FogLogic.");
		}

		private static void CacheReflection()
		{
			Type type = AccessTools.TypeByName("LevelGenerator");
			Type type2 = AccessTools.TypeByName("EnvironmentDirector");
			if (type != null)
			{
				_lgInstanceField = AccessTools.Field(type, "Instance");
				_lgGeneratedField = AccessTools.Field(type, "Generated");
			}
			if (type2 != null)
			{
				_envFogColorField = AccessTools.Field(type2, "FogColor");
				_envFogStartField = AccessTools.Field(type2, "FogStartDistance");
				_envFogEndField = AccessTools.Field(type2, "FogEndDistance");
				_envMainCameraField = AccessTools.Field(type2, "MainCamera");
				_envSetupDoneField = AccessTools.Field(type2, "SetupDone");
			}
			Type type3 = AccessTools.TypeByName("RunManager");
			if (type3 != null)
			{
				_rmInstanceField = AccessTools.Field(type3, "instance");
				_rmLevelCurrentField = AccessTools.Field(type3, "levelCurrent");
				_rmLevelMainMenuField = AccessTools.Field(type3, "levelMainMenu");
				_rmLevelLobbyMenuField = AccessTools.Field(type3, "levelLobbyMenu");
				_rmLevelSplashScreenField = AccessTools.Field(type3, "levelSplashScreen");
				_rmLevelIsShopField = AccessTools.Field(type3, "levelIsShop");
			}
		}

		private static Camera? GetEnvCamera(object envInstance)
		{
			object? obj = _envMainCameraField?.GetValue(envInstance);
			return (Camera?)(((obj is Camera) ? obj : null) ?? Camera.main);
		}

		private static void LoadFogBundle()
		{
			//IL_00a0: 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_00b6: Expected O, but got Unknown
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "betterfog");
			if (!File.Exists(text))
			{
				Log.LogError((object)("betterfog bundle not found at: " + text));
				return;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Failed to load betterfog bundle.");
				return;
			}
			Shader val2 = val.LoadAsset<Shader>("CylindricalFog");
			if ((Object)(object)val2 == (Object)null)
			{
				Log.LogError((object)"CylindricalFog shader not in bundle.");
				val.Unload(true);
				return;
			}
			_fogMaterial = new Material(val2)
			{
				name = "CylindricalFogMat"
			};
			val.Unload(false);
			Log.LogInfo((object)"Cylindrical fog shader loaded.");
		}

		private static bool IsLevelGenerated()
		{
			if (_lgInstanceField == null || _lgGeneratedField == null)
			{
				return false;
			}
			object value = _lgInstanceField.GetValue(null);
			return value != null && (bool)(_lgGeneratedField.GetValue(value) ?? ((object)false));
		}

		private static bool IsLevelActive(object envInstance)
		{
			if (!IsLevelGenerated())
			{
				return false;
			}
			if (_envSetupDoneField == null)
			{
				return true;
			}
			return (bool)(_envSetupDoneField.GetValue(envInstance) ?? ((object)false));
		}

		private static bool IsGameplayLevel()
		{
			if (_rmInstanceField == null || _rmLevelCurrentField == null)
			{
				return true;
			}
			object value = _rmInstanceField.GetValue(null);
			if (value == null)
			{
				return true;
			}
			object value2 = _rmLevelCurrentField.GetValue(value);
			if (value2 == null)
			{
				return false;
			}
			if (_rmLevelMainMenuField != null && value2 == _rmLevelMainMenuField.GetValue(value))
			{
				return false;
			}
			if (_rmLevelLobbyMenuField != null && value2 == _rmLevelLobbyMenuField.GetValue(value))
			{
				return false;
			}
			if (_rmLevelSplashScreenField != null && value2 == _rmLevelSplashScreenField.GetValue(value))
			{
				return false;
			}
			return true;
		}

		private static bool IsShopLevel()
		{
			if (_rmInstanceField == null || _rmLevelIsShopField == null)
			{
				return false;
			}
			object value = _rmInstanceField.GetValue(null);
			return value != null && (bool)(_rmLevelIsShopField.GetValue(value) ?? ((object)false));
		}

		private void Update()
		{
			if (!(_cachedEnvInstance != (Object)null) || !IsLevelActive(_cachedEnvInstance) || !IsGameplayLevel())
			{
				if ((Object)(object)_fogEffect != (Object)null)
				{
					Object.Destroy((Object)(object)_fogEffect);
					_fogEffect = null;
				}
				RenderSettings.fog = true;
			}
		}

		private void LateUpdate()
		{
			float farClipPlane = ((Time.frameCount - _lastPostfixFrame <= 5 && _cachedEnvInstance != (Object)null && IsLevelActive(_cachedEnvInstance) && IsGameplayLevel()) ? _desiredFarClip : 5000f);
			Camera[] allCameras = Camera.allCameras;
			foreach (Camera val in allCameras)
			{
				val.farClipPlane = farClipPlane;
			}
		}

		private static void FogLogic_Postfix(object __instance)
		{
			//IL_010b: 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_0110: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_lastPostfixFrame = Time.frameCount;
				_cachedEnvInstance = (Object?)((__instance is Object) ? __instance : null);
				if (!IsLevelActive(__instance) || !IsGameplayLevel())
				{
					if ((Object)(object)_fogEffect != (Object)null)
					{
						Object.Destroy((Object)(object)_fogEffect);
						_fogEffect = null;
					}
					RenderSettings.fog = true;
					_desiredFarClip = 5000f;
					Camera envCamera = GetEnvCamera(__instance);
					if ((Object)(object)envCamera != (Object)null)
					{
						envCamera.farClipPlane = 5000f;
					}
				}
				else
				{
					if ((Object)(object)_fogMaterial == (Object)null)
					{
						return;
					}
					if (!_enableBetterFog.Value)
					{
						if ((Object)(object)_fogEffect != (Object)null)
						{
							Object.Destroy((Object)(object)_fogEffect);
							_fogEffect = null;
						}
						RenderSettings.fog = true;
						return;
					}
					Color val = (Color)((_envFogColorField != null) ? ((Color)_envFogColorField.GetValue(__instance)) : Color.gray);
					bool flag = IsShopLevel();
					float num = (flag ? _shopFogStartOverride.Value : _fogStartOverride.Value);
					float num2 = (flag ? _shopFogEndOverride.Value : _fogEndOverride.Value);
					num2 = Mathf.Max(num2, num + 0.01f);
					if ((Object)(object)_fogEffect == (Object)null)
					{
						Camera envCamera2 = GetEnvCamera(__instance);
						if ((Object)(object)envCamera2 != (Object)null)
						{
							_fogEffect = CylindricalFogEffect.Attach(envCamera2, _fogMaterial);
						}
					}
					_fogMaterial.SetColor("_FogColor", val);
					_fogMaterial.SetFloat("_FogStart", num);
					_fogMaterial.SetFloat("_FogEnd", num2);
					if ((Object)(object)_fogEffect != (Object)null)
					{
						_fogEffect.FogColorVal = val;
						_fogEffect.FogStartVal = num;
						_fogEffect.FogEndVal = num2;
					}
					_desiredFarClip = num2 + 30f;
					Camera envCamera3 = GetEnvCamera(__instance);
					if ((Object)(object)envCamera3 != (Object)null)
					{
						envCamera3.farClipPlane = num2 + 30f;
					}
					RenderSettings.fog = false;
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"FogLogic_Postfix: {arg}");
			}
		}
	}
	internal class CylindricalFogEffect : MonoBehaviour
	{
		private static readonly int TempRT = Shader.PropertyToID("_CylFogTemp");

		private CommandBuffer? _cmd;

		private Material? _mat;

		private readonly Vector3[] _frustumCorners = (Vector3[])(object)new Vector3[4];

		internal Color FogColorVal = Color.gray;

		internal float FogStartVal;

		internal float FogEndVal = 200f;

		internal static CylindricalFogEffect Attach(Camera cam, Material mat)
		{
			CylindricalFogEffect cylindricalFogEffect = ((Component)cam).gameObject.AddComponent<CylindricalFogEffect>();
			cylindricalFogEffect._mat = mat;
			cylindricalFogEffect.Setup(cam);
			return cylindricalFogEffect;
		}

		private void Setup(Camera cam)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			cam.depthTextureMode = (DepthTextureMode)(cam.depthTextureMode | 1);
			_cmd = new CommandBuffer
			{
				name = "CylindricalFog"
			};
			cam.AddCommandBuffer((CameraEvent)18, _cmd);
		}

		private void OnPreRender()
		{
			//IL_0040: 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_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_00ad: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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)
			if (!((Object)(object)_mat == (Object)null) && _cmd != null)
			{
				Camera component = ((Component)this).GetComponent<Camera>();
				component.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), 1f, (MonoOrStereoscopicEye)2, _frustumCorners);
				_mat.SetVector("_FrustumBottomLeft", Vector4.op_Implicit(_frustumCorners[0]));
				_mat.SetVector("_FrustumTopLeft", Vector4.op_Implicit(_frustumCorners[1]));
				_mat.SetVector("_FrustumTopRight", Vector4.op_Implicit(_frustumCorners[2]));
				_mat.SetVector("_FrustumBottomRight", Vector4.op_Implicit(_frustumCorners[3]));
				_mat.SetMatrix("_CylFogCameraToWorld", component.cameraToWorldMatrix);
				Vector3 val = (((Object)(object)PlayerAvatar.instance != (Object)null && (Object)(object)PlayerAvatar.instance.playerTransform != (Object)null) ? PlayerAvatar.instance.playerTransform.position : ((Component)component).transform.position);
				_mat.SetVector("_FogOrigin", Vector4.op_Implicit(val));
				_cmd.Clear();
				_cmd.GetTemporaryRT(TempRT, -1, -1, 0, (FilterMode)1, (RenderTextureFormat)9);
				_cmd.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2), RenderTargetIdentifier.op_Implicit(TempRT), _mat);
				_cmd.Blit(RenderTargetIdentifier.op_Implicit(TempRT), RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2));
				_cmd.ReleaseTemporaryRT(TempRT);
			}
		}

		private void OnDestroy()
		{
			Camera component = ((Component)this).GetComponent<Camera>();
			if ((Object)(object)component != (Object)null && _cmd != null)
			{
				component.RemoveCommandBuffer((CameraEvent)18, _cmd);
			}
			CommandBuffer? cmd = _cmd;
			if (cmd != null)
			{
				cmd.Dispose();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BetterFog";

		public const string PLUGIN_NAME = "BetterFog";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}