Decompiled source of BetterLab v1.0.0

Mods/BetterLab.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BetterLab;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using Il2CppHorizonBasedAmbientOcclusion.Universal;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppMK.Glow;
using Il2CppMK.Glow.URP;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.XR;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "BetterLab", "1.0.0", "RUcreator", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BetterLab")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterLab")]
[assembly: AssemblyTitle("BetterLab")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 BetterLab
{
	public static class Assets
	{
		private static AssetBundle bundle;

		private static bool tried;

		public static bool Loaded => (Object)(object)bundle != (Object)null;

		public static void Load()
		{
			if (tried)
			{
				return;
			}
			tried = true;
			try
			{
				using Stream stream = typeof(Assets).Assembly.GetManifestResourceStream("BetterLab.betterlab.bundle") ?? throw new Exception("embedded bundle missing");
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				byte[] array = memoryStream.ToArray();
				string text = Path.Combine(MelonEnvironment.UserDataDirectory, "BetterLab");
				Directory.CreateDirectory(text);
				string text2 = Convert.ToHexString(SHA1.HashData(array)).Substring(0, 12);
				string text3 = Path.Combine(text, "betterlab_" + text2 + ".bundle");
				if (!File.Exists(text3))
				{
					string[] files = Directory.GetFiles(text, "betterlab_*.bundle");
					foreach (string path in files)
					{
						try
						{
							File.Delete(path);
						}
						catch
						{
						}
					}
					File.WriteAllBytes(text3, array);
				}
				bundle = AssetBundle.LoadFromFile(text3);
				if ((Object)(object)bundle == (Object)null)
				{
					throw new Exception("AssetBundle.LoadFromFile returned null for " + text3);
				}
				((Object)bundle).hideFlags = (HideFlags)32;
				MelonLogger.Msg($"BetterLab assets loaded ({array.Length / 1024} KB): " + string.Join(", ", Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)bundle.GetAllAssetNames())));
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("BetterLab: weather assets not loaded, sky/rain/snow/sounds disabled: " + ex.Message);
			}
		}

		public static T Get<T>(string name) where T : Object
		{
			if ((Object)(object)bundle == (Object)null)
			{
				return default(T);
			}
			try
			{
				Object val = bundle.LoadAsset(name, Il2CppType.Of<T>());
				if (val == (Object)null)
				{
					MelonLogger.Warning("BetterLab: asset not in bundle: " + name);
					return default(T);
				}
				val.hideFlags = (HideFlags)32;
				return ((Il2CppObjectBase)val).Cast<T>();
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("BetterLab: could not load " + name + ": " + ex.Message);
				return default(T);
			}
		}
	}
	public sealed class Core : MelonMod
	{
		private static float warnedAt = -10f;

		private static bool started;

		private static bool dirty = true;

		private static bool texDirty;

		private static float slowTick;

		private static TexMode lastTex;

		private static UniversalAdditionalCameraData camData;

		private static bool camPostOrig;

		private static EnumElement presetEl;

		private static EnumElement resModeEl;

		private static EnumElement msaaEl;

		private static EnumElement shadowsEl;

		private static EnumElement aoEl;

		private static EnumElement ssrEl;

		private static EnumElement texEl;

		private static EnumElement detailEl;

		private static EnumElement bloomEl;

		private static EnumElement bloomQEl;

		private static EnumElement toneEl;

		private static EnumElement godEl;

		private static FloatElement resEl;

		private static FloatElement minResEl;

		private static FloatElement sharpEl;

		private static FloatElement expEl;

		private static FloatElement conEl;

		private static FloatElement satEl;

		private static FloatElement tempEl;

		private static FloatElement vigEl;

		private static FloatElement chromaEl;

		private static FloatElement grainEl;

		private static BoolElement flareEl;

		private static BoolElement glareEl;

		private static BoolElement dirtEl;

		public static Camera Camera { get; private set; }

		public override void OnInitializeMelon()
		{
			try
			{
				Settings.Init();
				Settings.Changed += delegate
				{
					dirty = true;
				};
				lastTex = Settings.Textures;
				Assets.Load();
				BuildMenu();
				Hooking.OnLevelLoaded += delegate
				{
					MelonCoroutines.Start(AfterLevelLoad());
				};
				started = true;
				((MelonBase)this).LoggerInstance.Msg($"BetterLab ready: {(Settings.Enabled ? "ON" : "OFF")}, preset {Settings.Preset}, weather {Settings.Weather}");
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("BetterLab could not start: " + ex);
			}
		}

		private static IEnumerator AfterLevelLoad()
		{
			yield return null;
			yield return null;
			try
			{
				RefreshCamera(log: true);
				Pipeline.Refresh();
				Pipeline.Apply();
				DynamicResolution.Reset();
				Weather.OnLevelLoaded();
				dirty = true;
			}
			catch (Exception ex)
			{
				Warn("level load: " + ex);
			}
			float until = Time.realtimeSinceStartup + 3f;
			while (Time.realtimeSinceStartup < until)
			{
				yield return null;
			}
			try
			{
				Pipeline.ApplyTextures(force: true);
				MelonLogger.Msg("BetterLab status: " + Status(full: true));
			}
			catch (Exception ex2)
			{
				Warn("level load (late): " + ex2);
			}
		}

		public override void OnUpdate()
		{
			if (!started)
			{
				return;
			}
			try
			{
				if (Time.unscaledTime > slowTick)
				{
					slowTick = Time.unscaledTime + 1f;
					RefreshCamera(log: false);
					if (Pipeline.Refresh())
					{
						MelonLogger.Msg("BetterLab: the game switched its pipeline asset (graphics quality changed)");
						DynamicResolution.Reset();
						dirty = true;
					}
					else if (Settings.Enabled)
					{
						Pipeline.Apply(restoreGame: false);
					}
				}
				if (dirty)
				{
					dirty = false;
					if (!Settings.Enabled)
					{
						Pipeline.RestoreAll();
						Weather.Disable();
					}
					else
					{
						Pipeline.Apply();
					}
					if (Settings.Textures != lastTex || texDirty)
					{
						lastTex = Settings.Textures;
						texDirty = false;
						Pipeline.ApplyTextures(force: true);
					}
					Weather.SettingsChanged();
					ApplyCameraPost();
					PostFx.Apply();
				}
				DynamicResolution.Update();
				Weather.Update();
				if (Weather.Animating)
				{
					PostFx.Apply();
				}
			}
			catch (Exception ex)
			{
				Warn(ex.ToString());
			}
		}

		public override void OnLateUpdate()
		{
			if (!started)
			{
				return;
			}
			try
			{
				Weather.LateUpdate();
			}
			catch (Exception ex)
			{
				Warn(ex.ToString());
			}
		}

		private static void RefreshCamera(bool log)
		{
			//IL_019c: 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)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Camera val = Camera.main;
			if ((Object)(object)val == (Object)null && (Object)(object)Player.Head != (Object)null)
			{
				val = ((Component)Player.Head).GetComponentInChildren<Camera>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool flag = (Object)(object)Camera == (Object)null || ((Il2CppObjectBase)val).Pointer != ((Il2CppObjectBase)Camera).Pointer;
			Camera = val;
			if (flag || log)
			{
				if (flag)
				{
					camData = ((Component)val).GetComponent<UniversalAdditionalCameraData>();
					camPostOrig = (Object)(object)camData != (Object)null && camData.renderPostProcessing;
				}
				LayerMask volumeLayerMask;
				if (PostFx.Ensure() && (Object)(object)camData != (Object)null)
				{
					volumeLayerMask = camData.volumeLayerMask;
					PostFx.FitLayer(((LayerMask)(ref volumeLayerMask)).value);
				}
				ApplyCameraPost();
				string obj = $"BetterLab: camera '{Path(((Component)val).transform)}' far {val.farClipPlane:0} m, stereo {val.stereoEnabled}, ";
				object obj2;
				if (!((Object)(object)camData != (Object)null))
				{
					obj2 = "no URP camera data";
				}
				else
				{
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(45, 5);
					defaultInterpolatedStringHandler.AppendLiteral("post ");
					defaultInterpolatedStringHandler.AppendFormatted(camPostOrig);
					defaultInterpolatedStringHandler.AppendLiteral(" (now ");
					defaultInterpolatedStringHandler.AppendFormatted(camData.renderPostProcessing);
					defaultInterpolatedStringHandler.AppendLiteral("), volume mask 0x");
					volumeLayerMask = camData.volumeLayerMask;
					defaultInterpolatedStringHandler.AppendFormatted(((LayerMask)(ref volumeLayerMask)).value, "X");
					defaultInterpolatedStringHandler.AppendLiteral(", AA ");
					defaultInterpolatedStringHandler.AppendFormatted<AntialiasingMode>(camData.antialiasing);
					defaultInterpolatedStringHandler.AppendLiteral(", renderer #");
					defaultInterpolatedStringHandler.AppendFormatted(camData.m_RendererIndex);
					obj2 = defaultInterpolatedStringHandler.ToStringAndClear();
				}
				MelonLogger.Msg(obj + (string?)obj2);
			}
		}

		private static void ApplyCameraPost()
		{
			if (!((Object)(object)camData == (Object)null))
			{
				bool flag = Settings.Enabled || camPostOrig;
				if (camData.renderPostProcessing != flag)
				{
					camData.renderPostProcessing = flag;
				}
			}
		}

		private static string Path(Transform t)
		{
			string text = ((Object)t).name;
			Transform parent = t.parent;
			while ((Object)(object)parent != (Object)null && text.Length < 120)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static void BuildMenu()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_015b: 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_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0599: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_079f: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0829: Unknown result type (might be due to invalid IL or missing references)
			//IL_085e: Unknown result type (might be due to invalid IL or missing references)
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			Page obj = Page.Root.CreatePage("BetterLab", new Color(0.3f, 0.85f, 1f), 0, true);
			obj.CreateBool("BetterLab On/Off", Color.green, Settings.Enabled, (Action<bool>)delegate(bool v)
			{
				Settings.Enabled = v;
				Notify("BetterLab " + (v ? "ON" : "OFF (game graphics)"));
			});
			presetEl = obj.CreateEnum("Preset", new Color(1f, 0.8f, 0.2f), (Enum)Settings.Preset, (Action<Enum>)delegate(Enum v)
			{
				Preset preset = (Preset)(object)v;
				if (preset != Preset.Custom)
				{
					Presets.Apply(preset);
					SyncMenu();
					texDirty = true;
					Notify($"Preset {preset}: {Presets.Describe(preset)}", 5f);
				}
			});
			obj.CreateEnum("Weather", new Color(0.6f, 0.8f, 1f), (Enum)Settings.Weather, (Action<Enum>)delegate(Enum v)
			{
				Settings.Weather = (WeatherType)(object)v;
				Notify("Weather: " + v);
			});
			obj.CreateFloat("Weather intensity", new Color(0.6f, 0.8f, 1f), Settings.WeatherIntensity, 0.25f, 0.25f, 1.5f, (Action<float>)delegate(float v)
			{
				Settings.WeatherIntensity = v;
			});
			Page obj2 = obj.CreatePage("Graphics", Color.white, 0, true);
			resModeEl = obj2.CreateEnum("Resolution mode", Color.white, (Enum)Settings.ResMode, (Action<Enum>)delegate(Enum v)
			{
				Settings.ResMode = (ResMode)(object)v;
			});
			resEl = obj2.CreateFloat("Resolution (max)", Color.white, Settings.Resolution, 0.05f, 0.5f, 2f, (Action<float>)delegate(float v)
			{
				Settings.Resolution = v;
			});
			minResEl = obj2.CreateFloat("Auto: min resolution", Color.white, Settings.MinResolution, 0.05f, 0.5f, 2f, (Action<float>)delegate(float v)
			{
				Settings.MinResolution = v;
			});
			msaaEl = obj2.CreateEnum("Anti-aliasing (MSAA)", Color.white, (Enum)Settings.Msaa, (Action<Enum>)delegate(Enum v)
			{
				Settings.Msaa = (Msaa)(object)v;
			});
			shadowsEl = obj2.CreateEnum("Shadows", Color.white, (Enum)Settings.Shadows, (Action<Enum>)delegate(Enum v)
			{
				Settings.Shadows = (Quality4)(object)v;
			});
			aoEl = obj2.CreateEnum("Ambient occlusion", Color.white, (Enum)Settings.Ao, (Action<Enum>)delegate(Enum v)
			{
				Settings.Ao = (AoMode)(object)v;
			});
			ssrEl = obj2.CreateEnum("Reflections (SSR)", Color.white, (Enum)Settings.Ssr, (Action<Enum>)delegate(Enum v)
			{
				Settings.Ssr = (Reflections)(object)v;
			});
			texEl = obj2.CreateEnum("Textures", Color.white, (Enum)Settings.Textures, (Action<Enum>)delegate(Enum v)
			{
				Settings.Textures = (TexMode)(object)v;
			});
			detailEl = obj2.CreateEnum("Detail distance", Color.white, (Enum)Settings.Detail, (Action<Enum>)delegate(Enum v)
			{
				Settings.Detail = (Detail)(object)v;
			});
			sharpEl = obj2.CreateFloat("Sharpen (FSR, test)", Color.yellow, Settings.Sharpen, 0.1f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Settings.Sharpen = v;
			});
			Page obj3 = obj.CreatePage("Effects", Color.white, 0, true);
			bloomEl = obj3.CreateEnum("Bloom", Color.white, (Enum)Settings.Bloom, (Action<Enum>)delegate(Enum v)
			{
				Settings.Bloom = (BloomMode)(object)v;
			});
			bloomQEl = obj3.CreateEnum("Bloom quality", Color.white, (Enum)Settings.BloomQuality, (Action<Enum>)delegate(Enum v)
			{
				Settings.BloomQuality = (Quality4)(object)v;
			});
			flareEl = obj3.CreateBool("Lens flare", Color.white, Settings.LensFlare, (Action<bool>)delegate(bool v)
			{
				Settings.LensFlare = v;
			});
			glareEl = obj3.CreateBool("Glare streaks", Color.white, Settings.Glare, (Action<bool>)delegate(bool v)
			{
				Settings.Glare = v;
			});
			dirtEl = obj3.CreateBool("Lens dirt", Color.white, Settings.LensDirt, (Action<bool>)delegate(bool v)
			{
				Settings.LensDirt = v;
			});
			godEl = obj3.CreateEnum("God rays", Color.white, (Enum)Settings.GodRays, (Action<Enum>)delegate(Enum v)
			{
				Settings.GodRays = (GodRays)(object)v;
			});
			toneEl = obj3.CreateEnum("Tonemapping", Color.white, (Enum)Settings.Tonemap, (Action<Enum>)delegate(Enum v)
			{
				Settings.Tonemap = (ToneMap)(object)v;
			});
			expEl = obj3.CreateFloat("Exposure", Color.white, Settings.Exposure, 0.1f, -2f, 2f, (Action<float>)delegate(float v)
			{
				Settings.Exposure = v;
			});
			conEl = obj3.CreateFloat("Contrast", Color.white, Settings.Contrast, 2f, -50f, 50f, (Action<float>)delegate(float v)
			{
				Settings.Contrast = v;
			});
			satEl = obj3.CreateFloat("Saturation", Color.white, Settings.Saturation, 2f, -50f, 50f, (Action<float>)delegate(float v)
			{
				Settings.Saturation = v;
			});
			tempEl = obj3.CreateFloat("Temperature", Color.white, Settings.Temperature, 2f, -50f, 50f, (Action<float>)delegate(float v)
			{
				Settings.Temperature = v;
			});
			vigEl = obj3.CreateFloat("Vignette", Color.white, Settings.Vignette, 0.02f, 0f, 0.6f, (Action<float>)delegate(float v)
			{
				Settings.Vignette = v;
			});
			chromaEl = obj3.CreateFloat("Chromatic aberration", Color.white, Settings.Chroma, 0.02f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Settings.Chroma = v;
			});
			grainEl = obj3.CreateFloat("Film grain", Color.white, Settings.Grain, 0.05f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Settings.Grain = v;
			});
			Page obj4 = obj.CreatePage("Weather options", new Color(0.6f, 0.8f, 1f), 0, true);
			obj4.CreateBool("Weather sounds", Color.white, Settings.WeatherSound, (Action<bool>)delegate(bool v)
			{
				Settings.WeatherSound = v;
			});
			obj4.CreateFloat("Weather volume", Color.white, Settings.WeatherVolume, 0.1f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Settings.WeatherVolume = v;
			});
			obj4.CreateBool("Lightning (storm)", Color.white, Settings.Lightning, (Action<bool>)delegate(bool v)
			{
				Settings.Lightning = v;
			});
			obj.CreateFunction("Show stats", Color.white, (Action)delegate
			{
				Notify(Status(full: false), 8f);
			});
			obj.CreateFunction("Reapply preset", Color.yellow, (Action)delegate
			{
				Preset p = ((Settings.Preset == Preset.Custom) ? Preset.Balanced : Settings.Preset);
				Presets.Apply(p);
				SyncMenu();
				texDirty = true;
				Notify("Preset " + p.ToString() + " restored");
			});
		}

		private static void SyncMenu()
		{
			try
			{
				presetEl.Value = Settings.Preset;
				resModeEl.Value = Settings.ResMode;
				resEl.Value = Settings.Resolution;
				minResEl.Value = Settings.MinResolution;
				msaaEl.Value = Settings.Msaa;
				shadowsEl.Value = Settings.Shadows;
				aoEl.Value = Settings.Ao;
				ssrEl.Value = Settings.Ssr;
				texEl.Value = Settings.Textures;
				detailEl.Value = Settings.Detail;
				sharpEl.Value = Settings.Sharpen;
				bloomEl.Value = Settings.Bloom;
				bloomQEl.Value = Settings.BloomQuality;
				flareEl.Value = Settings.LensFlare;
				glareEl.Value = Settings.Glare;
				dirtEl.Value = Settings.LensDirt;
				godEl.Value = Settings.GodRays;
				toneEl.Value = Settings.Tonemap;
				expEl.Value = Settings.Exposure;
				conEl.Value = Settings.Contrast;
				satEl.Value = Settings.Saturation;
				tempEl.Value = Settings.Temperature;
				vigEl.Value = Settings.Vignette;
				chromaEl.Value = Settings.Chroma;
				grainEl.Value = Settings.Grain;
			}
			catch (Exception ex)
			{
				Warn("menu sync: " + ex.Message);
			}
		}

		private static string Status(bool full)
		{
			float value = ((Time.unscaledDeltaTime > 0f) ? (1f / Time.unscaledDeltaTime) : 0f);
			string text = $"{(Settings.Enabled ? "ON" : "OFF")}, preset {Settings.Preset}; {value:0} FPS (headset {DynamicResolution.RefreshRate:0} Hz), render scale {(((Object)(object)Pipeline.Asset != (Object)null) ? Pipeline.Asset.renderScale : 0f):0.00}" + (DynamicResolution.Active ? $" auto [{Settings.MinResolution:0.00}..{Settings.Resolution:0.00}], frame {DynamicResolution.LastMedianMs:0.0} ms, late {DynamicResolution.LateShare:P0}" : "") + "; " + Weather.Describe();
			if (full)
			{
				text = text + "\n  pipeline: " + Pipeline.Describe() + "\n  post: " + PostFx.Describe();
			}
			return text;
		}

		public static void Notify(string text, float seconds = 2.5f)
		{
			//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_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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			MelonLogger.Msg(text);
			try
			{
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("BetterLab"),
					Message = NotificationText.op_Implicit(text),
					Type = (NotificationType)0,
					PopupLength = seconds,
					ShowTitleOnPopup = true
				});
			}
			catch (Exception)
			{
			}
		}

		public static void Debug(string text)
		{
			MelonLogger.Msg("BetterLab: " + text);
		}

		public static void Warn(string text)
		{
			if (Time.realtimeSinceStartup - warnedAt > 3f)
			{
				warnedAt = Time.realtimeSinceStartup;
				MelonLogger.Warning("BetterLab: " + text);
			}
		}
	}
	public static class DynamicResolution
	{
		private const float Window = 1f;

		private const float StepUp = 0.05f;

		private const float StepDown = 0.1f;

		private const float UpQuiet = 6f;

		private const float CeilingMemory = 60f;

		private static readonly List<float> frames = new List<float>(256);

		private static float windowStart;

		private static float lastChange;

		private static float lastDrop = -999f;

		private static float ceiling = 9f;

		private static float graceUntil;

		private static float scale = -1f;

		private static float refresh;

		private static float estimate;

		private static readonly Queue<float> medians = new Queue<float>();

		private static bool triedXr;

		public static float Scale => scale;

		public static float RefreshRate
		{
			get
			{
				if (!(refresh > 0f))
				{
					return estimate;
				}
				return refresh;
			}
		}

		public static float LastMedianMs { get; private set; }

		public static float LateShare { get; private set; }

		public static bool Active
		{
			get
			{
				if (Settings.Enabled && Settings.ResMode == ResMode.Auto)
				{
					return (Object)(object)Pipeline.Asset != (Object)null;
				}
				return false;
			}
		}

		public static void Reset()
		{
			frames.Clear();
			windowStart = Time.unscaledTime;
			graceUntil = Time.unscaledTime + 4f;
			scale = -1f;
			ceiling = 9f;
		}

		private static void FindRefresh()
		{
			if (triedXr)
			{
				return;
			}
			triedXr = true;
			try
			{
				List<XRDisplaySubsystem> val = new List<XRDisplaySubsystem>();
				SubsystemManager.GetInstances<XRDisplaySubsystem>(val);
				float num = default(float);
				for (int i = 0; i < val.Count; i++)
				{
					if (val[i] != null && ((IntegratedSubsystem)val[i]).running && val[i].TryGetDisplayRefreshRate(ref num) && num > 30f)
					{
						refresh = num;
						break;
					}
				}
				MelonLogger.Msg($"BetterLab: headset refresh rate {((refresh > 0f) ? (refresh.ToString("0") + " Hz") : "unknown (will measure)")}, eye texture {XRSettings.eyeTextureWidth}x{XRSettings.eyeTextureHeight}, eye scale {XRSettings.eyeTextureResolutionScale:0.00}");
			}
			catch (Exception ex)
			{
				MelonLogger.Msg("BetterLab: refresh rate query failed (" + ex.Message + "), will measure it");
			}
		}

		public static void Update()
		{
			if (!Active)
			{
				if (scale > 0f)
				{
					Reset();
				}
				return;
			}
			FindRefresh();
			float num = Mathf.Min(Settings.MinResolution, Settings.Resolution);
			float resolution = Settings.Resolution;
			if (scale < 0f)
			{
				scale = resolution;
				lastChange = Time.unscaledTime;
				Pipeline.SetRenderScale(scale);
			}
			if (Mathf.Abs(Mathf.Clamp(scale, num, resolution) - scale) > 0.001f)
			{
				scale = Mathf.Clamp(scale, num, resolution);
				Pipeline.SetRenderScale(scale);
			}
			if (Time.unscaledTime < graceUntil || (Object)(object)Player.RigManager == (Object)null)
			{
				frames.Clear();
				windowStart = Time.unscaledTime;
				return;
			}
			frames.Add(Time.unscaledDeltaTime);
			if (Time.unscaledTime - windowStart < 1f)
			{
				return;
			}
			windowStart = Time.unscaledTime;
			frames.Sort();
			float num2 = frames[frames.Count / 2];
			LastMedianMs = num2 * 1000f;
			medians.Enqueue(num2);
			while (medians.Count > 30)
			{
				medians.Dequeue();
			}
			float num3 = float.MaxValue;
			foreach (float median in medians)
			{
				num3 = Mathf.Min(num3, median);
			}
			estimate = Snap(1f / num3);
			float num4 = 1f / Mathf.Max(30f, RefreshRate);
			int num5 = 0;
			foreach (float frame in frames)
			{
				if (frame > num4 * 1.35f)
				{
					num5++;
				}
			}
			LateShare = (float)num5 / (float)frames.Count;
			frames.Clear();
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - lastChange < 1.5f || Time.timeScale < 0.01f)
			{
				return;
			}
			if (LateShare > 0.08f || num2 > num4 * 1.15f)
			{
				if (scale > num + 0.001f)
				{
					ceiling = scale;
					lastDrop = unscaledTime;
					Set(Mathf.Max(num, scale - 0.1f), $"late frames {LateShare:P0}, median {num2 * 1000f:0.0} ms vs {num4 * 1000f:0.0}");
				}
			}
			else if (LateShare < 0.01f && unscaledTime - lastChange > 6f && scale < resolution - 0.001f)
			{
				float num6 = Mathf.Min(resolution, scale + 0.05f);
				if (unscaledTime - lastDrop > 60f || num6 < ceiling - 0.001f)
				{
					Set(num6, "headroom");
				}
			}
		}

		private static float Snap(float hz)
		{
			float[] obj = new float[6] { 60f, 72f, 80f, 90f, 120f, 144f };
			float result = hz;
			float num = float.MaxValue;
			float[] array = obj;
			foreach (float num2 in array)
			{
				if (Mathf.Abs(num2 - hz) < num)
				{
					num = Mathf.Abs(num2 - hz);
					result = num2;
				}
			}
			if (!(num < 6f))
			{
				return hz;
			}
			return result;
		}

		private static void Set(float s, string why)
		{
			scale = s;
			lastChange = Time.unscaledTime;
			Pipeline.SetRenderScale(s);
			Core.Debug($"auto resolution -> {s:0.00} ({why})");
		}
	}
	public static class Pipeline
	{
		private sealed class Orig
		{
			public UniversalRenderPipelineAsset asset;

			public float renderScale;

			public float shadowDistance;

			public float cascadeBorder;

			public float ssrHit;

			public float fsrSharp;

			public int msaa;

			public int cascades;

			public int lightsPerObject;

			public int ssrSteps;

			public int ssrMinMip;

			public int upscaling;

			public ShadowResolution mainShadowRes;

			public ShadowResolution addShadowRes;

			public bool soft;

			public bool ssr;

			public bool fsrOverride;
		}

		private static readonly Dictionary<IntPtr, Orig> origs = new Dictionary<IntPtr, Orig>();

		private static UniversalRenderPipelineAsset asset;

		private static float origLodBias = -1f;

		private static float appliedLod = -1f;

		private static int appliedAniso = -1;

		private static AnisotropicFiltering origAniso;

		private static bool qualityCaptured;

		private static readonly Dictionary<IntPtr, (Texture2D tex, float bias, int aniso)> texOrig = new Dictionary<IntPtr, (Texture2D, float, int)>();

		private static TexMode texApplied = TexMode.Game;

		public static UniversalRenderPipelineAsset Asset => asset;

		public static string AssetName
		{
			get
			{
				if (!((Object)(object)asset != (Object)null))
				{
					return "none";
				}
				return ((Object)asset).name;
			}
		}

		private static Orig O
		{
			get
			{
				if (!((Object)(object)asset != (Object)null) || !origs.TryGetValue(((Il2CppObjectBase)asset).Pointer, out var value))
				{
					return null;
				}
				return value;
			}
		}

		public static float GameRenderScale => O?.renderScale ?? 1f;

		public static bool Refresh()
		{
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected I4, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected I4, but got Unknown
			RenderPipelineAsset val = null;
			try
			{
				val = GraphicsSettings.currentRenderPipeline;
			}
			catch
			{
			}
			UniversalRenderPipelineAsset val2 = (((Object)(object)val != (Object)null) ? ((Il2CppObjectBase)val).TryCast<UniversalRenderPipelineAsset>() : null);
			bool result = (((Object)(object)val2 == (Object)null) ? ((Object)(object)asset != (Object)null) : ((Object)(object)asset == (Object)null || ((Il2CppObjectBase)val2).Pointer != ((Il2CppObjectBase)asset).Pointer));
			asset = val2;
			if ((Object)(object)asset != (Object)null && !origs.ContainsKey(((Il2CppObjectBase)asset).Pointer))
			{
				origs[((Il2CppObjectBase)asset).Pointer] = new Orig
				{
					asset = asset,
					renderScale = asset.renderScale,
					msaa = asset.msaaSampleCount,
					shadowDistance = asset.shadowDistance,
					cascades = asset.m_ShadowCascadeCount,
					cascadeBorder = asset.m_CascadeBorder,
					mainShadowRes = asset.m_MainLightShadowmapResolution,
					addShadowRes = asset.m_AdditionalLightsShadowmapResolution,
					lightsPerObject = asset.m_AdditionalLightsPerObjectLimit,
					soft = asset.m_SoftShadowsSupported,
					ssr = asset.m_EnableSSR,
					ssrSteps = asset.m_MaxSsrSteps,
					ssrMinMip = asset.m_SsrMinMip,
					ssrHit = asset.m_SsrHitRadius,
					upscaling = (int)asset.m_UpscalingFilter,
					fsrOverride = asset.m_FsrOverrideSharpness,
					fsrSharp = asset.m_FsrSharpness
				};
				MelonLogger.Msg("BetterLab: pipeline asset " + Describe());
			}
			if (!qualityCaptured)
			{
				qualityCaptured = true;
				try
				{
					origLodBias = QualitySettings.lodBias;
				}
				catch
				{
					origLodBias = 2f;
				}
				try
				{
					origAniso = QualitySettings.anisotropicFiltering;
				}
				catch
				{
					origAniso = (AnisotropicFiltering)2;
				}
				appliedLod = origLodBias;
				appliedAniso = (int)origAniso;
				MelonLogger.Msg($"BetterLab: game LOD bias {origLodBias}, anisotropic {origAniso}");
			}
			return result;
		}

		public static void SetRenderScale(float s)
		{
			if ((Object)(object)asset != (Object)null && Mathf.Abs(asset.renderScale - s) > 0.004f)
			{
				asset.renderScale = s;
			}
		}

		public static void Apply(bool restoreGame = true)
		{
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Invalid comparison between I4 and Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Expected I4, but got Unknown
			Refresh();
			Orig o = O;
			if ((Object)(object)asset == (Object)null || o == null)
			{
				return;
			}
			bool enabled = Settings.Enabled;
			try
			{
				if (!enabled || Settings.ResMode == ResMode.Game)
				{
					if (restoreGame)
					{
						SetRenderScale(o.renderScale);
					}
				}
				else if (Settings.ResMode == ResMode.Fixed)
				{
					SetRenderScale(Settings.Resolution);
				}
				int num = (enabled ? (Settings.Msaa switch
				{
					Msaa.Off => 1, 
					Msaa.X2 => 2, 
					Msaa.X4 => 4, 
					Msaa.X8 => 8, 
					_ => o.msaa, 
				}) : o.msaa);
				int num2 = num;
				if (asset.msaaSampleCount != num2 && (restoreGame || (enabled && Settings.Msaa != Msaa.Game)))
				{
					asset.msaaSampleCount = num2;
				}
				switch (enabled ? Settings.Shadows : Quality4.Game)
				{
				case Quality4.Low:
					SetShadows(30f, 2, 0.1f, (ShadowResolution)1024, (ShadowResolution)1024, 4, soft: true);
					break;
				case Quality4.Medium:
					SetShadows(50f, 3, 0.1f, (ShadowResolution)2048, (ShadowResolution)2048, 6, soft: true);
					break;
				case Quality4.High:
					SetShadows(100f, 4, 0.0667f, (ShadowResolution)4096, (ShadowResolution)4096, 8, soft: true);
					break;
				case Quality4.Ultra:
					SetShadows(150f, 4, 0.05f, (ShadowResolution)4096, (ShadowResolution)4096, 8, soft: true);
					break;
				default:
					if (restoreGame)
					{
						SetShadows(o.shadowDistance, o.cascades, o.cascadeBorder, o.mainShadowRes, o.addShadowRes, o.lightsPerObject, o.soft);
					}
					break;
				}
				switch (enabled ? Settings.Ssr : Reflections.Game)
				{
				case Reflections.Off:
					asset.m_EnableSSR = false;
					break;
				case Reflections.On:
					asset.m_EnableSSR = true;
					asset.m_MaxSsrSteps = 35;
					asset.m_SsrMinMip = 0;
					asset.m_SsrHitRadius = 0.025f;
					break;
				case Reflections.High:
					asset.m_EnableSSR = true;
					asset.m_MaxSsrSteps = 64;
					asset.m_SsrMinMip = 0;
					asset.m_SsrHitRadius = 0.02f;
					break;
				default:
					if (restoreGame)
					{
						asset.m_EnableSSR = o.ssr;
						asset.m_MaxSsrSteps = o.ssrSteps;
						asset.m_SsrMinMip = o.ssrMinMip;
						asset.m_SsrHitRadius = o.ssrHit;
					}
					break;
				}
				float num3 = (enabled ? Settings.Sharpen : 0f);
				if (num3 > 0.01f)
				{
					asset.m_UpscalingFilter = (UpscalingFilterSelection)3;
					asset.m_FsrOverrideSharpness = true;
					asset.m_FsrSharpness = num3;
				}
				else if (restoreGame)
				{
					asset.m_UpscalingFilter = (UpscalingFilterSelection)o.upscaling;
					asset.m_FsrOverrideSharpness = o.fsrOverride;
					asset.m_FsrSharpness = o.fsrSharp;
				}
			}
			catch (Exception ex)
			{
				Core.Warn("pipeline: " + ex.Message);
			}
			try
			{
				float num4 = (enabled ? (Settings.Detail switch
				{
					Detail.Near => 1.2f, 
					Detail.Normal => 2f, 
					Detail.Far => 3f, 
					Detail.Ultra => 4.5f, 
					_ => origLodBias, 
				}) : origLodBias);
				float num5 = num4;
				bool flag = !enabled || Settings.Detail == Detail.Game;
				if (num5 > 0f && Mathf.Abs(appliedLod - num5) > 0.001f && (restoreGame || !flag))
				{
					QualitySettings.lodBias = num5;
					appliedLod = num5;
				}
				TexMode texMode = (enabled ? Settings.Textures : TexMode.Game);
				AnisotropicFiltering val = (AnisotropicFiltering)((texMode != TexMode.Game) ? 2 : ((int)origAniso));
				if (appliedAniso != (int)val && (restoreGame || texMode != TexMode.Game))
				{
					QualitySettings.anisotropicFiltering = val;
					appliedAniso = (int)val;
				}
			}
			catch (Exception ex2)
			{
				Core.Warn("quality: " + ex2.Message);
			}
		}

		private static void SetShadows(float dist, int cascades, float border, ShadowResolution main, ShadowResolution add, int lights, bool soft)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (Mathf.Abs(asset.shadowDistance - dist) > 0.01f)
			{
				asset.shadowDistance = dist;
			}
			asset.m_ShadowCascadeCount = cascades;
			asset.m_CascadeBorder = border;
			asset.m_MainLightShadowmapResolution = main;
			asset.m_AdditionalLightsShadowmapResolution = add;
			asset.m_AdditionalLightsPerObjectLimit = lights;
			asset.m_SoftShadowsSupported = soft;
		}

		public static void ApplyTextures(bool force = false)
		{
			TexMode texMode = (Settings.Enabled ? Settings.Textures : TexMode.Game);
			if (!force && texMode == texApplied && texMode == TexMode.Game)
			{
				return;
			}
			texApplied = texMode;
			float num = texMode switch
			{
				TexMode.Sharp => -0.3f, 
				TexMode.UltraSharp => -0.6f, 
				_ => 0f, 
			};
			int num2 = 0;
			int num3 = 0;
			try
			{
				if (texMode == TexMode.Game)
				{
					foreach (KeyValuePair<IntPtr, (Texture2D, float, int)> item2 in texOrig)
					{
						Texture2D item = item2.Value.Item1;
						if (!((Object)(object)item == (Object)null))
						{
							((Texture)item).mipMapBias = 0f;
							((Texture)item).anisoLevel = item2.Value.Item3;
							num3++;
						}
					}
					texOrig.Clear();
				}
				else
				{
					foreach (Object item3 in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<Texture2D>()))
					{
						Texture2D val = ((Il2CppObjectBase)item3).TryCast<Texture2D>();
						if ((Object)(object)val == (Object)null || ((Texture)val).mipmapCount <= 1)
						{
							continue;
						}
						string name = ((Object)val).name;
						if (!name.StartsWith("Lightmap", StringComparison.OrdinalIgnoreCase) && !name.Contains("_lightmap", StringComparison.OrdinalIgnoreCase))
						{
							if (!texOrig.ContainsKey(((Il2CppObjectBase)val).Pointer))
							{
								texOrig[((Il2CppObjectBase)val).Pointer] = (val, 0f, ((Texture)val).anisoLevel);
							}
							((Texture)val).mipMapBias = num;
							if (((Texture)val).anisoLevel < 16)
							{
								((Texture)val).anisoLevel = 16;
							}
							num2++;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Core.Warn("textures: " + ex.Message);
			}
			MelonLogger.Msg($"BetterLab: textures {texMode}: {num2} set (mip bias {num}), {num3} restored");
		}

		public static void RestoreAll()
		{
			//IL_0096: 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)
			foreach (Orig value in origs.Values)
			{
				UniversalRenderPipelineAsset val = value.asset;
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					if (Mathf.Abs(val.renderScale - value.renderScale) > 0.004f)
					{
						val.renderScale = value.renderScale;
					}
					if (val.msaaSampleCount != value.msaa)
					{
						val.msaaSampleCount = value.msaa;
					}
					val.shadowDistance = value.shadowDistance;
					val.m_ShadowCascadeCount = value.cascades;
					val.m_CascadeBorder = value.cascadeBorder;
					val.m_MainLightShadowmapResolution = value.mainShadowRes;
					val.m_AdditionalLightsShadowmapResolution = value.addShadowRes;
					val.m_AdditionalLightsPerObjectLimit = value.lightsPerObject;
					val.m_SoftShadowsSupported = value.soft;
					val.m_EnableSSR = value.ssr;
					val.m_MaxSsrSteps = value.ssrSteps;
					val.m_SsrMinMip = value.ssrMinMip;
					val.m_SsrHitRadius = value.ssrHit;
					val.m_UpscalingFilter = (UpscalingFilterSelection)value.upscaling;
					val.m_FsrOverrideSharpness = value.fsrOverride;
					val.m_FsrSharpness = value.fsrSharp;
				}
				catch (Exception ex)
				{
					Core.Warn("restore: " + ex.Message);
				}
			}
			Apply();
			ApplyTextures(force: true);
		}

		public static string Describe()
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)asset == (Object)null)
			{
				return "no URP asset";
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder3 = stringBuilder2;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 4, stringBuilder2);
			handler.AppendLiteral("'");
			handler.AppendFormatted(((Object)asset).name);
			handler.AppendLiteral("': scale ");
			handler.AppendFormatted(asset.renderScale, "0.00");
			handler.AppendLiteral(", MSAA ");
			handler.AppendFormatted(asset.msaaSampleCount);
			handler.AppendLiteral(", HDR ");
			handler.AppendFormatted(asset.supportsHDR);
			handler.AppendLiteral(", ");
			stringBuilder3.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(22, 4, stringBuilder2);
			handler.AppendLiteral("shadows ");
			handler.AppendFormatted(asset.shadowDistance, "0");
			handler.AppendLiteral(" m x");
			handler.AppendFormatted(asset.m_ShadowCascadeCount);
			handler.AppendLiteral(" ");
			handler.AppendFormatted<ShadowResolution>(asset.m_MainLightShadowmapResolution);
			handler.AppendLiteral(", soft ");
			handler.AppendFormatted(asset.m_SoftShadowsSupported);
			handler.AppendLiteral(", ");
			stringBuilder4.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(31, 3, stringBuilder2);
			handler.AppendLiteral("lights/object ");
			handler.AppendFormatted(asset.m_AdditionalLightsPerObjectLimit);
			handler.AppendLiteral(", SSR ");
			handler.AppendFormatted(asset.m_EnableSSR);
			handler.AppendLiteral(" (");
			handler.AppendFormatted(asset.m_MaxSsrSteps);
			handler.AppendLiteral(" steps), ");
			stringBuilder5.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(28, 3, stringBuilder2);
			handler.AppendLiteral("opaque tex ");
			handler.AppendFormatted(asset.m_RequireOpaqueTexture);
			handler.AppendLiteral(" (");
			handler.AppendFormatted<Downsampling>(asset.m_OpaqueDownsampling);
			handler.AppendLiteral("), depth tex ");
			handler.AppendFormatted(asset.m_RequireDepthTexture);
			handler.AppendLiteral(", ");
			stringBuilder6.Append(ref handler);
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder7 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(36, 3, stringBuilder2);
			handler.AppendLiteral("upscaling ");
			handler.AppendFormatted<UpscalingFilterSelection>(asset.m_UpscalingFilter);
			handler.AppendLiteral(", grading ");
			handler.AppendFormatted<ColorGradingMode>(asset.m_ColorGradingMode);
			handler.AppendLiteral(", volume update ");
			handler.AppendFormatted<VolumeFrameworkUpdateMode>(asset.m_VolumeFrameworkUpdateMode);
			stringBuilder7.Append(ref handler);
			try
			{
				Il2CppReferenceArray<ScriptableRendererData> rendererDataList = asset.m_RendererDataList;
				int num = 0;
				while (rendererDataList != null && num < ((Il2CppArrayBase<ScriptableRendererData>)(object)rendererDataList).Length)
				{
					ScriptableRendererData val = ((Il2CppArrayBase<ScriptableRendererData>)(object)rendererDataList)[num];
					if (!((Object)(object)val == (Object)null))
					{
						stringBuilder2 = stringBuilder;
						StringBuilder stringBuilder8 = stringBuilder2;
						handler = new StringBuilder.AppendInterpolatedStringHandler(24, 2, stringBuilder2);
						handler.AppendLiteral("; renderer ");
						handler.AppendFormatted(num);
						handler.AppendLiteral(" '");
						handler.AppendFormatted(((Object)val).name);
						handler.AppendLiteral("' features:");
						stringBuilder8.Append(ref handler);
						List<ScriptableRendererFeature> rendererFeatures = val.rendererFeatures;
						int num2 = 0;
						while (rendererFeatures != null && num2 < rendererFeatures.Count)
						{
							ScriptableRendererFeature val2 = rendererFeatures[num2];
							stringBuilder.Append(((Object)(object)val2 == (Object)null) ? " (null)" : (" " + ((Object)val2).name + (val2.isActive ? "" : "(off)")));
							num2++;
						}
						UniversalRendererData val3 = ((Il2CppObjectBase)val).TryCast<UniversalRendererData>();
						if ((Object)(object)val3 != (Object)null)
						{
							stringBuilder2 = stringBuilder;
							StringBuilder stringBuilder9 = stringBuilder2;
							handler = new StringBuilder.AppendInterpolatedStringHandler(12, 1, stringBuilder2);
							handler.AppendLiteral(", post data ");
							handler.AppendFormatted(((Object)(object)val3.postProcessData != (Object)null) ? "yes" : "NO");
							stringBuilder9.Append(ref handler);
						}
					}
					num++;
				}
			}
			catch (Exception ex)
			{
				stringBuilder.Append("; renderers: " + ex.Message);
			}
			try
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder10 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(18, 2, stringBuilder2);
				handler.AppendLiteral("; lodBias ");
				handler.AppendFormatted(appliedLod);
				handler.AppendLiteral(", aniso ");
				handler.AppendFormatted<AnisotropicFiltering>((AnisotropicFiltering)appliedAniso);
				stringBuilder10.Append(ref handler);
			}
			catch (Exception ex2)
			{
				stringBuilder.Append("; quality: " + ex2.Message);
			}
			return stringBuilder.ToString();
		}
	}
	public struct Grade
	{
		public float exposure;

		public float contrast;

		public float saturation;

		public float temperature;

		public float tint;

		public float bloom;

		public float vignette;

		public Color filter;

		public static Grade Lerp(Grade a, Grade b, float t)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			return new Grade
			{
				exposure = Mathf.Lerp(a.exposure, b.exposure, t),
				contrast = Mathf.Lerp(a.contrast, b.contrast, t),
				saturation = Mathf.Lerp(a.saturation, b.saturation, t),
				temperature = Mathf.Lerp(a.temperature, b.temperature, t),
				tint = Mathf.Lerp(a.tint, b.tint, t),
				bloom = Mathf.Lerp(a.bloom, b.bloom, t),
				vignette = Mathf.Lerp(a.vignette, b.vignette, t),
				filter = Color.Lerp(a.filter, b.filter, t)
			};
		}
	}
	public static class PostFx
	{
		private static GameObject go;

		private static Volume volume;

		private static VolumeProfile profile;

		private static MKGlow mk;

		private static HBAO hbao;

		private static Tonemapping tone;

		private static ColorAdjustments color;

		private static WhiteBalance white;

		private static Vignette vig;

		private static ChromaticAberration chroma;

		private static FilmGrain grain;

		private static Volumetrics volumetrics;

		private static Texture2D lensDirt;

		private static bool failed;

		public static bool Ready => (Object)(object)volume != (Object)null;

		public static string Layer
		{
			get
			{
				if (!((Object)(object)go != (Object)null))
				{
					return "-";
				}
				return LayerMask.LayerToName(go.layer) + " (" + go.layer + ")";
			}
		}

		private static T Add<T>() where T : VolumeComponent
		{
			try
			{
				T val = ((Il2CppObjectBase)profile.Add(Il2CppType.Of<T>(), false)).Cast<T>();
				((VolumeComponent)val).active = true;
				((Object)(object)val).hideFlags = (HideFlags)32;
				return val;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning($"BetterLab: no {typeof(T).Name} effect ({ex.Message})");
				return default(T);
			}
		}

		public static bool Ensure()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if ((Object)(object)volume != (Object)null)
			{
				return true;
			}
			if (failed)
			{
				return false;
			}
			try
			{
				go = new GameObject("BetterLab Volume");
				Object.DontDestroyOnLoad((Object)(object)go);
				volume = go.AddComponent<Volume>();
				volume.isGlobal = true;
				volume.priority = 100f;
				volume.weight = 1f;
				profile = ScriptableObject.CreateInstance<VolumeProfile>();
				((Object)profile).name = "BetterLab";
				((Object)profile).hideFlags = (HideFlags)32;
				mk = Add<MKGlow>();
				hbao = Add<HBAO>();
				tone = Add<Tonemapping>();
				color = Add<ColorAdjustments>();
				white = Add<WhiteBalance>();
				vig = Add<Vignette>();
				chroma = Add<ChromaticAberration>();
				grain = Add<FilmGrain>();
				volumetrics = Add<Volumetrics>();
				volume.sharedProfile = profile;
				lensDirt = Assets.Get<Texture2D>("LensDirt");
				MelonLogger.Msg($"BetterLab: volume ready ({profile.components.Count} effects)");
				return true;
			}
			catch (Exception ex)
			{
				failed = true;
				MelonLogger.Error("BetterLab: could not create the post-processing volume: " + ex);
				return false;
			}
		}

		public static void FitLayer(int mask)
		{
			if ((Object)(object)go == (Object)null || mask == 0 || (mask & (1 << go.layer)) != 0)
			{
				return;
			}
			for (int i = 0; i < 32; i++)
			{
				if ((mask & (1 << i)) != 0)
				{
					go.layer = i;
					MelonLogger.Msg($"BetterLab: volume moved to layer {i} ({LayerMask.LayerToName(i)})");
					break;
				}
			}
		}

		private static void P<T>(VolumeParameter<T> p, T v)
		{
			((VolumeParameter)p).overrideState = true;
			p.value = v;
		}

		private static void Off(VolumeParameter p)
		{
			if (p != null)
			{
				p.overrideState = false;
			}
		}

		private static void Grading(bool set, VolumeParameter<float> p, float v, float min, float max)
		{
			if (set)
			{
				P(p, Mathf.Clamp(v, min, max));
			}
			else
			{
				Off((VolumeParameter)(object)p);
			}
		}

		private static T BaseValue<T, TC>(Func<TC, VolumeParameter<T>> sel, T def) where TC : VolumeComponent
		{
			try
			{
				List<Volume> volumes = VolumeManager.instance.m_Volumes;
				float num = float.MinValue;
				T result = def;
				int num2 = 0;
				while (volumes != null && num2 < volumes.Count)
				{
					Volume val = volumes[num2];
					if (!((Object)(object)val == (Object)null) && !(((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)volume).Pointer) && ((Behaviour)val).isActiveAndEnabled && val.isGlobal && !(val.weight <= 0f) && !(val.priority < num))
					{
						VolumeProfile val2 = (val.HasInstantiatedProfile() ? val.profile : val.sharedProfile);
						if (!((Object)(object)val2 == (Object)null))
						{
							List<VolumeComponent> components = val2.components;
							for (int i = 0; i < components.Count; i++)
							{
								VolumeComponent obj = components[i];
								TC val3 = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<TC>() : default(TC));
								if (!((Object)(object)val3 == (Object)null) && ((VolumeComponent)val3).active)
								{
									VolumeParameter<T> val4 = sel(val3);
									if (val4 != null && ((VolumeParameter)val4).overrideState)
									{
										result = val4.value;
										num = val.priority;
									}
								}
							}
						}
					}
					num2++;
				}
				return result;
			}
			catch
			{
				return def;
			}
		}

		private static float Base<TC>(Func<TC, VolumeParameter<float>> sel, float def) where TC : VolumeComponent
		{
			return BaseValue(sel, def);
		}

		private static Color BaseColor<TC>(Func<TC, VolumeParameter<Color>> sel, Color def) where TC : VolumeComponent
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return BaseValue(sel, def);
		}

		public static void Apply()
		{
			if (!Ensure())
			{
				return;
			}
			bool enabled = Settings.Enabled;
			Grade grade = Weather.Grade;
			float flash = Weather.Flash;
			try
			{
				ApplyBloom(enabled, grade);
			}
			catch (Exception ex)
			{
				Core.Warn("bloom: " + ex.Message);
			}
			try
			{
				ApplyAo(enabled);
			}
			catch (Exception ex2)
			{
				Core.Warn("ao: " + ex2.Message);
			}
			try
			{
				ApplyGrading(enabled, grade, flash);
			}
			catch (Exception ex3)
			{
				Core.Warn("grading: " + ex3.Message);
			}
			try
			{
				ApplyVolumetrics(enabled);
			}
			catch (Exception ex4)
			{
				Core.Warn("volumetrics: " + ex4.Message);
			}
		}

		private static void ApplyBloom(bool on, Grade w)
		{
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mk == (Object)null)
			{
				return;
			}
			BloomMode bloomMode = (on ? Settings.Bloom : BloomMode.Game);
			float num = 1f + w.bloom;
			switch (bloomMode)
			{
			case BloomMode.Off:
				P((VolumeParameter<float>)(object)mk.bloomIntensity, 0f);
				Off((VolumeParameter)(object)mk.bloomScattering);
				break;
			case BloomMode.Soft:
				P((VolumeParameter<float>)(object)mk.bloomIntensity, 1.8f * num);
				P((VolumeParameter<float>)(object)mk.bloomScattering, 6f);
				break;
			case BloomMode.Normal:
				P((VolumeParameter<float>)(object)mk.bloomIntensity, 3f * num);
				P((VolumeParameter<float>)(object)mk.bloomScattering, 7f);
				break;
			case BloomMode.Strong:
				P((VolumeParameter<float>)(object)mk.bloomIntensity, 4.5f * num);
				P((VolumeParameter<float>)(object)mk.bloomScattering, 8f);
				break;
			default:
				if (on && Mathf.Abs(w.bloom) > 0.01f)
				{
					P((VolumeParameter<float>)(object)mk.bloomIntensity, BaseValue<float, MKGlow>((Func<MKGlow, VolumeParameter<float>>)((MKGlow c) => (VolumeParameter<float>)(object)c.bloomIntensity), 3f) * num);
				}
				else
				{
					Off((VolumeParameter)(object)mk.bloomIntensity);
				}
				Off((VolumeParameter)(object)mk.bloomScattering);
				break;
			}
			Quality4 quality = (on ? Settings.BloomQuality : Quality4.Game);
			if (quality == Quality4.Game)
			{
				Off((VolumeParameter)(object)mk.quality);
			}
			else
			{
				VolumeParameter<Quality> quality2 = (VolumeParameter<Quality>)(object)mk.quality;
				P<Quality>(quality2, (Quality)(quality switch
				{
					Quality4.Low => 8, 
					Quality4.Medium => 4, 
					Quality4.High => 2, 
					_ => 1, 
				}));
			}
			if (on && Settings.LensFlare)
			{
				P((VolumeParameter<bool>)(object)mk.allowLensFlare, v: true);
				P<LensFlareStyle>((VolumeParameter<LensFlareStyle>)(object)mk.lensFlareStyle, (LensFlareStyle)1);
				P((VolumeParameter<float>)(object)mk.lensFlareGhostIntensity, 0.7f);
				P((VolumeParameter<float>)(object)mk.lensFlareHaloIntensity, 0.6f);
			}
			else
			{
				Off((VolumeParameter)(object)mk.allowLensFlare);
				Off((VolumeParameter)(object)mk.lensFlareStyle);
				Off((VolumeParameter)(object)mk.lensFlareGhostIntensity);
				Off((VolumeParameter)(object)mk.lensFlareHaloIntensity);
			}
			if (on && Settings.Glare)
			{
				P((VolumeParameter<bool>)(object)mk.allowGlare, v: true);
				P<GlareStyle>((VolumeParameter<GlareStyle>)(object)mk.glareStyle, (GlareStyle)1);
				P((VolumeParameter<float>)(object)mk.glareIntensity, 0.8f);
				P((VolumeParameter<float>)(object)mk.glareBlend, 0.33f);
				P((VolumeParameter<float>)(object)mk.glareScattering, 2f);
				P<MinMaxRange>((VolumeParameter<MinMaxRange>)(object)mk.glareThreshold, new MinMaxRange
				{
					minValue = 1.4f,
					maxValue = 10f
				});
			}
			else
			{
				Off((VolumeParameter)(object)mk.allowGlare);
				Off((VolumeParameter)(object)mk.glareStyle);
				Off((VolumeParameter)(object)mk.glareIntensity);
				Off((VolumeParameter)(object)mk.glareBlend);
				Off((VolumeParameter)(object)mk.glareScattering);
				Off((VolumeParameter)(object)mk.glareThreshold);
			}
			if (on && Settings.LensDirt && (Object)(object)lensDirt != (Object)null)
			{
				P((VolumeParameter<bool>)(object)mk.allowLensSurface, v: true);
				P<Texture2D>((VolumeParameter<Texture2D>)(object)mk.lensSurfaceDirtTexture, lensDirt);
				P((VolumeParameter<float>)(object)mk.lensSurfaceDirtIntensity, 2.5f);
			}
			else
			{
				Off((VolumeParameter)(object)mk.allowLensSurface);
				Off((VolumeParameter)(object)mk.lensSurfaceDirtTexture);
				Off((VolumeParameter)(object)mk.lensSurfaceDirtIntensity);
			}
		}

		private static void ApplyAo(bool on)
		{
			if ((Object)(object)hbao == (Object)null)
			{
				return;
			}
			AoMode aoMode = (on ? Settings.Ao : AoMode.Game);
			switch (aoMode)
			{
			case AoMode.Game:
			{
				VolumeParameter[] array = (VolumeParameter[])(object)new VolumeParameter[12]
				{
					(VolumeParameter)hbao.intensity,
					(VolumeParameter)hbao.quality,
					(VolumeParameter)hbao.resolution,
					(VolumeParameter)hbao.radius,
					(VolumeParameter)hbao.mode,
					(VolumeParameter)hbao.blurType,
					(VolumeParameter)hbao.useMultiBounce,
					(VolumeParameter)hbao.colorBleedingEnabled,
					(VolumeParameter)hbao.saturation,
					(VolumeParameter)hbao.perPixelNormals,
					(VolumeParameter)hbao.noiseType,
					(VolumeParameter)hbao.bias
				};
				for (int i = 0; i < array.Length; i++)
				{
					Off(array[i]);
				}
				return;
			}
			case AoMode.Off:
				P((VolumeParameter<float>)(object)hbao.intensity, 0f);
				return;
			}
			P<Mode>((VolumeParameter<Mode>)(object)hbao.mode, (Mode)1);
			P<PerPixelNormals>((VolumeParameter<PerPixelNormals>)(object)hbao.perPixelNormals, (PerPixelNormals)2);
			P<NoiseType>((VolumeParameter<NoiseType>)(object)hbao.noiseType, (NoiseType)1);
			P((VolumeParameter<float>)(object)hbao.bias, 0.172f);
			switch (aoMode)
			{
			case AoMode.Low:
				P<Quality>((VolumeParameter<Quality>)(object)hbao.quality, (Quality)1);
				P<Resolution>((VolumeParameter<Resolution>)(object)hbao.resolution, (Resolution)1);
				P((VolumeParameter<float>)(object)hbao.intensity, 1.5f);
				P((VolumeParameter<float>)(object)hbao.radius, 0.3f);
				P<BlurType>((VolumeParameter<BlurType>)(object)hbao.blurType, (BlurType)1);
				P((VolumeParameter<bool>)(object)hbao.useMultiBounce, v: true);
				P((VolumeParameter<bool>)(object)hbao.colorBleedingEnabled, v: false);
				break;
			case AoMode.Medium:
				P<Quality>((VolumeParameter<Quality>)(object)hbao.quality, (Quality)2);
				P<Resolution>((VolumeParameter<Resolution>)(object)hbao.resolution, (Resolution)0);
				P((VolumeParameter<float>)(object)hbao.intensity, 1.8f);
				P((VolumeParameter<float>)(object)hbao.radius, 0.3f);
				P<BlurType>((VolumeParameter<BlurType>)(object)hbao.blurType, (BlurType)1);
				P((VolumeParameter<bool>)(object)hbao.useMultiBounce, v: true);
				P((VolumeParameter<bool>)(object)hbao.colorBleedingEnabled, v: false);
				break;
			case AoMode.High:
				P<Quality>((VolumeParameter<Quality>)(object)hbao.quality, (Quality)4);
				P<Resolution>((VolumeParameter<Resolution>)(object)hbao.resolution, (Resolution)0);
				P((VolumeParameter<float>)(object)hbao.intensity, 2.1f);
				P((VolumeParameter<float>)(object)hbao.radius, 0.35f);
				P<BlurType>((VolumeParameter<BlurType>)(object)hbao.blurType, (BlurType)1);
				P((VolumeParameter<bool>)(object)hbao.useMultiBounce, v: true);
				P((VolumeParameter<bool>)(object)hbao.colorBleedingEnabled, v: false);
				break;
			case AoMode.UltraGI:
				P<Quality>((VolumeParameter<Quality>)(object)hbao.quality, (Quality)4);
				P<Resolution>((VolumeParameter<Resolution>)(object)hbao.resolution, (Resolution)0);
				P((VolumeParameter<float>)(object)hbao.intensity, 2.2f);
				P((VolumeParameter<float>)(object)hbao.radius, 0.45f);
				P<BlurType>((VolumeParameter<BlurType>)(object)hbao.blurType, (BlurType)2);
				P((VolumeParameter<bool>)(object)hbao.useMultiBounce, v: true);
				P((VolumeParameter<bool>)(object)hbao.colorBleedingEnabled, v: true);
				P((VolumeParameter<float>)(object)hbao.saturation, 1.6f);
				break;
			}
		}

		private static void ApplyGrading(bool on, Grade w, float flash)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			ToneMap toneMap = (on ? Settings.Tonemap : ToneMap.Game);
			if ((Object)(object)tone != (Object)null)
			{
				if (toneMap == ToneMap.Game)
				{
					Off((VolumeParameter)(object)tone.mode);
				}
				else
				{
					VolumeParameter<TonemappingMode> mode = (VolumeParameter<TonemappingMode>)(object)tone.mode;
					P<TonemappingMode>(mode, (TonemappingMode)(toneMap switch
					{
						ToneMap.Neutral => 1, 
						ToneMap.ACES => 2, 
						_ => 0, 
					}));
				}
			}
			float num = (on ? Settings.Exposure : 0f) + w.exposure + flash * 1.6f;
			float num2 = (on ? Settings.Contrast : 0f) + w.contrast;
			float num3 = (on ? Settings.Saturation : 0f) + w.saturation;
			bool active = Weather.Active;
			if ((Object)(object)color != (Object)null)
			{
				Grading(on && Mathf.Abs(num) > 0.001f, (VolumeParameter<float>)(object)color.postExposure, Base<ColorAdjustments>((Func<ColorAdjustments, VolumeParameter<float>>)((ColorAdjustments c) => (VolumeParameter<float>)(object)c.postExposure), 0f) + num, -10f, 10f);
				Grading(on && Mathf.Abs(num2) > 0.01f, (VolumeParameter<float>)(object)color.contrast, Base<ColorAdjustments>((Func<ColorAdjustments, VolumeParameter<float>>)((ColorAdjustments c) => (VolumeParameter<float>)(object)c.contrast), 0f) + num2, -100f, 100f);
				Grading(on && Mathf.Abs(num3) > 0.01f, (VolumeParameter<float>)(object)color.saturation, Base<ColorAdjustments>((Func<ColorAdjustments, VolumeParameter<float>>)((ColorAdjustments c) => (VolumeParameter<float>)(object)c.saturation), 0f) + num3, -100f, 100f);
				if (on && active)
				{
					P<Color>((VolumeParameter<Color>)(object)color.colorFilter, BaseColor<ColorAdjustments>((Func<ColorAdjustments, VolumeParameter<Color>>)((ColorAdjustments c) => (VolumeParameter<Color>)(object)c.colorFilter), Color.white) * w.filter);
				}
				else
				{
					Off((VolumeParameter)(object)color.colorFilter);
				}
			}
			float num4 = (on ? Settings.Temperature : 0f) + w.temperature;
			if ((Object)(object)white != (Object)null)
			{
				Grading(on && Mathf.Abs(num4) > 0.01f, (VolumeParameter<float>)(object)white.temperature, Base<WhiteBalance>((Func<WhiteBalance, VolumeParameter<float>>)((WhiteBalance c) => (VolumeParameter<float>)(object)c.temperature), 0f) + num4, -100f, 100f);
				Grading(on && Mathf.Abs(w.tint) > 0.01f, (VolumeParameter<float>)(object)white.tint, Base<WhiteBalance>((Func<WhiteBalance, VolumeParameter<float>>)((WhiteBalance c) => (VolumeParameter<float>)(object)c.tint), 0f) + w.tint, -100f, 100f);
			}
			float num5 = (on ? Settings.Vignette : 0f) + w.vignette;
			if ((Object)(object)vig != (Object)null)
			{
				if (on && num5 > 0.001f)
				{
					num5 = Mathf.Max(num5, Base<Vignette>((Func<Vignette, VolumeParameter<float>>)((Vignette c) => (VolumeParameter<float>)(object)c.intensity), 0f) + w.vignette);
					P((VolumeParameter<float>)(object)vig.intensity, Mathf.Clamp01(num5));
					P((VolumeParameter<float>)(object)vig.smoothness, 0.45f);
					P<Color>((VolumeParameter<Color>)(object)vig.color, Color.black);
				}
				else
				{
					Off((VolumeParameter)(object)vig.intensity);
					Off((VolumeParameter)(object)vig.smoothness);
					Off((VolumeParameter)(object)vig.color);
				}
			}
			if ((Object)(object)chroma != (Object)null)
			{
				if (on && Settings.Chroma > 0.001f)
				{
					P((VolumeParameter<float>)(object)chroma.intensity, Settings.Chroma);
				}
				else
				{
					Off((VolumeParameter)(object)chroma.intensity);
				}
			}
			if ((Object)(object)grain != (Object)null)
			{
				if (on && Settings.Grain > 0.001f)
				{
					P<FilmGrainLookup>((VolumeParameter<FilmGrainLookup>)(object)grain.type, (FilmGrainLookup)1);
					P((VolumeParameter<float>)(object)grain.intensity, Settings.Grain);
					P((VolumeParameter<float>)(object)grain.response, 0.8f);
				}
				else
				{
					Off((VolumeParameter)(object)grain.type);
					Off((VolumeParameter)(object)grain.intensity);
					Off((VolumeParameter)(object)grain.response);
				}
			}
		}

		private static void ApplyVolumetrics(bool on)
		{
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)volumetrics == (Object)null))
			{
				GodRays godRays = (on ? Settings.GodRays : GodRays.Game);
				bool flag = (uint)(godRays - 2) <= 1u;
				float num = (flag ? BaseValue<float, Volumetrics>((Func<Volumetrics, VolumeParameter<float>>)((Volumetrics c) => (VolumeParameter<float>)(object)c.FogViewDistance), 50f) : 50f);
				float num2 = godRays switch
				{
					GodRays.Off => 3000f, 
					GodRays.Normal => Mathf.Clamp(num * 0.6f, 40f, 150f), 
					GodRays.Strong => Mathf.Clamp(num * 0.4f, 30f, 100f), 
					_ => 0f, 
				};
				float num3 = (on ? Weather.VolumetricFog : 0f);
				if (num3 > 0f)
				{
					num2 = ((num2 > 0f) ? Mathf.Min(num2, num3) : num3);
				}
				if (num2 > 0f)
				{
					P((VolumeParameter<float>)(object)volumetrics.FogViewDistance, num2);
				}
				else
				{
					Off((VolumeParameter)(object)volumetrics.FogViewDistance);
				}
				flag = on;
				if (flag)
				{
					bool flag2 = (uint)(godRays - 2) <= 1u;
					flag = flag2;
				}
				if (flag)
				{
					P((VolumeParameter<float>)(object)volumetrics.GlobalStaticLightMultiplier, (godRays == GodRays.Strong) ? 1.5f : 1.25f);
				}
				else
				{
					Off((VolumeParameter)(object)volumetrics.GlobalStaticLightMultiplier);
				}
				if (num3 > 0f)
				{
					P((VolumeParameter<float>)(object)volumetrics.FogBaseHeight, -10000f);
					P((VolumeParameter<float>)(object)volumetrics.FogMaxHeight, 10000f);
					P<Color>((VolumeParameter<Color>)(object)volumetrics.VolumetricAlbedo, Weather.FogAlbedo);
				}
				else
				{
					Off((VolumeParameter)(object)volumetrics.FogBaseHeight);
					Off((VolumeParameter)(object)volumetrics.FogMaxHeight);
					Off((VolumeParameter)(object)volumetrics.VolumetricAlbedo);
				}
				Cubemap val = (on ? Weather.SkyCube : null);
				if ((Object)(object)val != (Object)null)
				{
					P<Texture>((VolumeParameter<Texture>)(object)volumetrics.SkyTexture, (Texture)(object)val);
					P((VolumeParameter<bool>)(object)volumetrics.isNullSky, v: false);
				}
				else
				{
					Off((VolumeParameter)(object)volumetrics.SkyTexture);
					Off((VolumeParameter)(object)volumetrics.isNullSky);
				}
			}
		}

		public static string Describe()
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)volume == (Object)null)
			{
				return "volume not created";
			}
			try
			{
				VolumeStack stack = VolumeManager.instance.stack;
				VolumeComponent component = stack.GetComponent(Il2CppType.Of<MKGlow>());
				MKGlow val = ((component != null) ? ((Il2CppObjectBase)component).TryCast<MKGlow>() : null);
				VolumeComponent component2 = stack.GetComponent(Il2CppType.Of<HBAO>());
				HBAO val2 = ((component2 != null) ? ((Il2CppObjectBase)component2).TryCast<HBAO>() : null);
				VolumeComponent component3 = stack.GetComponent(Il2CppType.Of<Tonemapping>());
				Tonemapping val3 = ((component3 != null) ? ((Il2CppObjectBase)component3).TryCast<Tonemapping>() : null);
				VolumeComponent component4 = stack.GetComponent(Il2CppType.Of<Volumetrics>());
				Volumetrics val4 = ((component4 != null) ? ((Il2CppObjectBase)component4).TryCast<Volumetrics>() : null);
				return $"volume layer {Layer}, priority {volume.priority}; stack: " + (((Object)(object)val != (Object)null) ? $"MKGlow {((VolumeParameter<float>)(object)val.bloomIntensity).value:0.0} q{((VolumeParameter<Quality>)(object)val.quality).value} flare {((VolumeParameter<bool>)(object)val.allowLensFlare).value} glare {((VolumeParameter<bool>)(object)val.allowGlare).value}; " : "no MKGlow; ") + (((Object)(object)val2 != (Object)null) ? $"HBAO {((VolumeParameter<float>)(object)val2.intensity).value:0.0} {((VolumeParameter<Quality>)(object)val2.quality).value} {((VolumeParameter<Mode>)(object)val2.mode).value} bleed {((VolumeParameter<bool>)(object)val2.colorBleedingEnabled).value}; " : "no HBAO; ") + (((Object)(object)val3 != (Object)null) ? $"tonemap {((VolumeParameter<TonemappingMode>)(object)val3.mode).value}; " : "") + (((Object)(object)val4 != (Object)null) ? $"volumetric fog {((VolumeParameter<float>)(object)val4.FogViewDistance).value:0} m, light x{((VolumeParameter<float>)(object)val4.GlobalStaticLightMultiplier).value:0.00}" : "");
			}
			catch (Exception ex)
			{
				return "stack: " + ex.Message;
			}
		}
	}
	public static class Presets
	{
		public static bool Applying { get; private set; }

		public static string Describe(Preset p)
		{
			return p switch
			{
				Preset.Vanilla => "the game as it is (weather still works)", 
				Preset.Performance => "more FPS: lower resolution with auto scaling, no AO and reflections, short shadows", 
				Preset.Balanced => "better picture at the same FPS: auto resolution, AF16, finer bloom, light color grading", 
				Preset.Quality => "sharper and richer: higher resolution, ACES, better shadows, AO and reflections", 
				Preset.Ultra => "max quality: supersampling, ultra shadows, long detail distance, lens flares", 
				Preset.RTX => "fake ray tracing: supersampling, GI-like AO color bleeding, high reflections, glare, lens dirt", 
				_ => "your own settings", 
			};
		}

		public static void Apply(Preset p)
		{
			if (p == Preset.Custom)
			{
				return;
			}
			Applying = true;
			try
			{
				Settings.ResMode = ResMode.Game;
				Settings.Resolution = 1.1f;
				Settings.MinResolution = 0.8f;
				Settings.Msaa = Msaa.Game;
				Settings.Shadows = Quality4.Game;
				Settings.Ao = AoMode.Game;
				Settings.Ssr = Reflections.Game;
				Settings.Textures = TexMode.Game;
				Settings.Detail = Detail.Game;
				Settings.Sharpen = 0f;
				Settings.Bloom = BloomMode.Game;
				Settings.BloomQuality = Quality4.Game;
				Settings.LensFlare = false;
				Settings.Glare = false;
				Settings.LensDirt = false;
				Settings.Tonemap = ToneMap.Game;
				Settings.Exposure = 0f;
				Settings.Contrast = 0f;
				Settings.Saturation = 0f;
				Settings.Temperature = 0f;
				Settings.Vignette = 0f;
				Settings.Chroma = 0f;
				Settings.Grain = 0f;
				Settings.GodRays = GodRays.Game;
				switch (p)
				{
				case Preset.Performance:
					Settings.ResMode = ResMode.Auto;
					Settings.Resolution = 1f;
					Settings.MinResolution = 0.7f;
					Settings.Msaa = Msaa.X2;
					Settings.Shadows = Quality4.Low;
					Settings.Ao = AoMode.Off;
					Settings.Ssr = Reflections.Off;
					Settings.Detail = Detail.Near;
					Settings.Bloom = BloomMode.Soft;
					Settings.BloomQuality = Quality4.Low;
					Settings.GodRays = GodRays.Off;
					break;
				case Preset.Balanced:
					Settings.ResMode = ResMode.Auto;
					Settings.Resolution = 1.1f;
					Settings.MinResolution = 0.8f;
					Settings.Textures = TexMode.AF16;
					Settings.Detail = Detail.Normal;
					Settings.Bloom = BloomMode.Normal;
					Settings.BloomQuality = Quality4.Medium;
					Settings.Contrast = 5f;
					Settings.Saturation = 5f;
					Settings.Vignette = 0.12f;
					break;
				case Preset.Quality:
					Settings.ResMode = ResMode.Auto;
					Settings.Resolution = 1.25f;
					Settings.MinResolution = 0.9f;
					Settings.Msaa = Msaa.X4;
					Settings.Shadows = Quality4.High;
					Settings.Ao = AoMode.High;
					Settings.Ssr = Reflections.On;
					Settings.Textures = TexMode.Sharp;
					Settings.Detail = Detail.Far;
					Settings.Bloom = BloomMode.Normal;
					Settings.BloomQuality = Quality4.High;
					Settings.Tonemap = ToneMap.ACES;
					Settings.Exposure = 0.15f;
					Settings.Contrast = 8f;
					Settings.Saturation = 8f;
					Settings.Vignette = 0.15f;
					Settings.GodRays = GodRays.Normal;
					break;
				case Preset.Ultra:
					Settings.ResMode = ResMode.Auto;
					Settings.Resolution = 1.4f;
					Settings.MinResolution = 1f;
					Settings.Msaa = Msaa.X4;
					Settings.Shadows = Quality4.Ultra;
					Settings.Ao = AoMode.High;
					Settings.Ssr = Reflections.High;
					Settings.Textures = TexMode.UltraSharp;
					Settings.Detail = Detail.Ultra;
					Settings.Bloom = BloomMode.Normal;
					Settings.BloomQuality = Quality4.Ultra;
					Settings.LensFlare = true;
					Settings.Tonemap = ToneMap.ACES;
					Settings.Exposure = 0.15f;
					Settings.Contrast = 10f;
					Settings.Saturation = 10f;
					Settings.Vignette = 0.15f;
					Settings.GodRays = GodRays.Normal;
					break;
				case Preset.RTX:
					Settings.ResMode = ResMode.Auto;
					Settings.Resolution = 1.5f;
					Settings.MinResolution = 1f;
					Settings.Msaa = Msaa.X4;
					Settings.Shadows = Quality4.Ultra;
					Settings.Ao = AoMode.UltraGI;
					Settings.Ssr = Reflections.High;
					Settings.Textures = TexMode.UltraSharp;
					Settings.Detail = Detail.Ultra;
					Settings.Bloom = BloomMode.Strong;
					Settings.BloomQuality = Quality4.Ultra;
					Settings.LensFlare = true;
					Settings.Glare = true;
					Settings.LensDirt = true;
					Settings.Tonemap = ToneMap.ACES;
					Settings.Exposure = 0.2f;
					Settings.Contrast = 12f;
					Settings.Saturation = 12f;
					Settings.Vignette = 0.2f;
					Settings.Chroma = 0.06f;
					Settings.GodRays = GodRays.Strong;
					break;
				}
			}
			finally
			{
				Applying = false;
			}
			Settings.Preset = p;
		}
	}
	public enum Preset
	{
		Vanilla,
		Performance,
		Balanced,
		Quality,
		Ultra,
		RTX,
		Custom
	}
	public enum ResMode
	{
		Game,
		Fixed,
		Auto
	}
	public enum Msaa
	{
		Game,
		Off,
		X2,
		X4,
		X8
	}
	public enum Quality4
	{
		Game,
		Low,
		Medium,
		High,
		Ultra
	}
	public enum AoMode
	{
		Game,
		Off,
		Low,
		Medium,
		High,
		UltraGI
	}
	public enum Reflections
	{
		Game,
		Off,
		On,
		High
	}
	public enum TexMode
	{
		Game,
		AF16,
		Sharp,
		UltraSharp
	}
	public enum Detail
	{
		Game,
		Near,
		Normal,
		Far,
		Ultra
	}
	public enum BloomMode
	{
		Game,
		Off,
		Soft,
		Normal,
		Strong
	}
	public enum ToneMap
	{
		Game,
		Neutral,
		ACES,
		Off
	}
	public enum GodRays
	{
		Game,
		Off,
		Normal,
		Strong
	}
	public enum WeatherType
	{
		Level,
		Sunny,
		Clear,
		Cloudy,
		Overcast,
		Fog,
		Rain,
		Storm,
		Snow,
		Sunset,
		Night
	}
	public static class Settings
	{
		private static MelonPreferences_Category cat;

		private static bool loading;

		private static MelonPreferences_Entry<bool> enabled;

		private static MelonPreferences_Entry<bool> lensFlare;

		private static MelonPreferences_Entry<bool> glare;

		private static MelonPreferences_Entry<bool> lensDirt;

		private static MelonPreferences_Entry<bool> weatherSound;

		private static MelonPreferences_Entry<bool> lightning;

		private static MelonPreferences_Entry<string> preset;

		private static MelonPreferences_Entry<string> resMode;

		private static MelonPreferences_Entry<string> msaa;

		private static MelonPreferences_Entry<string> shadows;

		private static MelonPreferences_Entry<string> ao;

		private static MelonPreferences_Entry<string> ssr;

		private static MelonPreferences_Entry<string> tex;

		private static MelonPreferences_Entry<string> detail;

		private static MelonPreferences_Entry<string> bloom;

		private static MelonPreferences_Entry<string> bloomQuality;

		private static MelonPreferences_Entry<string> tonemap;

		private static MelonPreferences_Entry<string> godRays;

		private static MelonPreferences_Entry<string> weather;

		private static MelonPreferences_Entry<float> resolution;

		private static MelonPreferences_Entry<float> minResolution;

		private static MelonPreferences_Entry<float> sharpen;

		private static MelonPreferences_Entry<float> exposure;

		private static MelonPreferences_Entry<float> contrast;

		private static MelonPreferences_Entry<float> saturation;

		private static MelonPreferences_Entry<float> temperature;

		private static MelonPreferences_Entry<float> vignette;

		private static MelonPreferences_Entry<float> chroma;

		private static MelonPreferences_Entry<float> grain;

		private static MelonPreferences_Entry<float> weatherIntensity;

		private static MelonPreferences_Entry<float> weatherVolume;

		public static bool Enabled
		{
			get
			{
				return enabled.Value;
			}
			set
			{
				enabled.Value = value;
				Touch(custom: false);
			}
		}

		public static Preset Preset
		{
			get
			{
				return E(preset, Preset.Balanced);
			}
			set
			{
				preset.Value = value.ToString();
				Touch(custom: false);
			}
		}

		public static ResMode ResMode
		{
			get
			{
				return E(resMode, ResMode.Auto);
			}
			set
			{
				SetE(resMode, value);
			}
		}

		public static float Resolution
		{
			get
			{
				return Clamp(resolution.Value, 0.5f, 2f);
			}
			set
			{
				resolution.Value = Clamp(value, 0.5f, 2f);
				Touch(custom: true);
			}
		}

		public static float MinResolution
		{
			get
			{
				return Clamp(minResolution.Value, 0.5f, 2f);
			}
			set
			{
				minResolution.Value = Clamp(value, 0.5f, 2f);
				Touch(custom: true);
			}
		}

		public static Msaa Msaa
		{
			get
			{
				return E(msaa, Msaa.Game);
			}
			set
			{
				SetE(msaa, value);
			}
		}

		public static Quality4 Shadows
		{
			get
			{
				return E(shadows, Quality4.Game);
			}
			set
			{
				SetE(shadows, value);
			}
		}

		public static AoMode Ao
		{
			get
			{
				return E(ao, AoMode.Game);
			}
			set
			{
				SetE(ao, value);
			}
		}

		public static Reflections Ssr
		{
			get
			{
				return E(ssr, Reflections.Game);
			}
			set
			{
				SetE(ssr, value);
			}
		}

		public static TexMode Textures
		{
			get
			{
				return E(tex, TexMode.Game);
			}
			set
			{
				SetE(tex, value);
			}
		}

		public static Detail Detail
		{
			get
			{
				return E(detail, Detail.Game);
			}
			set
			{
				SetE(detail, value);
			}
		}

		public static float Sharpen
		{
			get
			{
				return Clamp(sharpen.Value, 0f, 1f);
			}
			set
			{
				sharpen.Value = Clamp(value, 0f, 1f);
				Touch(custom: true);
			}
		}

		public static BloomMode Bloom
		{
			get
			{
				return E(bloom, BloomMode.Game);
			}
			set
			{
				SetE(bloom, value);
			}
		}

		public static Quality4 BloomQuality
		{
			get
			{
				return E(bloomQuality, Quality4.Game);
			}
			set
			{
				SetE(bloomQuality, value);
			}
		}

		public static bool LensFlare
		{
			get
			{
				return lensFlare.Value;
			}
			set
			{
				lensFlare.Value = value;
				Touch(custom: true);
			}
		}

		public static bool Glare
		{
			get
			{
				return glare.Value;
			}
			set
			{
				glare.Value = value;
				Touch(custom: true);
			}
		}

		public static bool LensDirt
		{
			get
			{
				return lensDirt.Value;
			}
			set
			{
				lensDirt.Value = value;
				Touch(custom: true);
			}
		}

		public static ToneMap Tonemap
		{
			get
			{
				return E(tonemap, ToneMap.Game);
			}
			set
			{
				SetE(tonemap, value);
			}
		}

		public static float Exposure
		{
			get
			{
				return Clamp(exposure.Value, -2f, 2f);
			}
			set
			{
				exposure.Value = Clamp(value, -2f, 2f);
				Touch(custom: true);
			}
		}

		public static float Contrast
		{
			get
			{
				return Clamp(contrast.Value, -50f, 50f);
			}
			set
			{
				contrast.Value = Clamp(value, -50f, 50f);
				Touch(custom: true);
			}
		}

		public static float Saturation
		{
			get
			{
				return Clamp(saturation.Value, -50f, 50f);
			}
			set
			{
				saturation.Value = Clamp(value, -50f, 50f);
				Touch(custom: true);
			}
		}

		public static float Temperature
		{
			get
			{
				return Clamp(temperature.Value, -50f, 50f);
			}
			set
			{
				temperature.Value = Clamp(value, -50f, 50f);
				Touch(custom: true);
			}
		}

		public static float Vignette
		{
			get
			{
				return Clamp(vignette.Value, 0f, 0.6f);
			}
			set
			{
				vignette.Value = Clamp(value, 0f, 0.6f);
				Touch(custom: true);
			}
		}

		public static float Chroma
		{
			get
			{
				return Clamp(chroma.Value, 0f, 1f);
			}
			set
			{
				chroma.Value = Clamp(value, 0f, 1f);
				Touch(custom: true);
			}
		}

		public static float Grain
		{
			get
			{
				return Clamp(grain.Value, 0f, 1f);
			}
			set
			{
				grain.Value = Clamp(value, 0f, 1f);
				Touch(custom: true);
			}
		}

		public static GodRays GodRays
		{
			get
			{
				return E(godRays, GodRays.Game);
			}
			set
			{
				SetE(godRays, value);
			}
		}

		public static WeatherType Weather
		{
			get
			{
				return E(weather, WeatherType.Level);
			}
			set
			{
				SetE(weather, value, custom: false);
			}
		}

		public static float WeatherIntensity
		{
			get
			{
				return Clamp(weatherIntensity.Value, 0.25f, 1.5f);
			}
			set
			{
				weatherIntensity.Value = Clamp(value, 0.25f, 1.5f);
				Touch(custom: false);
			}
		}

		public static bool WeatherSound
		{
			get
			{
				return weatherSound.Value;
			}
			set
			{
				weatherSound.Value = value;
				Touch(custom: false);
			}
		}

		public static float WeatherVolume
		{
			get
			{
				return Clamp(weatherVolume.Value, 0f, 1f);
			}
			set
			{
				weatherVolume.Value = Clamp(value, 0f, 1f);
				Touch(custom: false);
			}
		}

		public static bool Lightning
		{
			get
			{
				return lightning.Value;
			}
			set
			{
				lightning.Value = value;
				Touch(custom: false);
			}
		}

		public static event Action Changed;

		public static void Init()
		{
			loading = true;
			cat = MelonPreferences.CreateCategory("BetterLab", "BetterLab");
			enabled = cat.CreateEntry<bool>("Enabled", true, "BetterLab on/off", (string)null, false, false, (ValueValidator)null, (string)null);
			preset = cat.CreateEntry<string>("Preset", "Balanced", "Vanilla, Performance, Balanced, Quality, Ultra, RTX, Custom", (string)null, false, false, (ValueValidator)null, (string)null);
			resMode = cat.CreateEntry<string>("ResolutionMode", "Auto", "Game, Fixed, Auto (dynamic resolution keeps the headset frame rate)", (string)null, false, false, (ValueValidator)null, (string)null);
			resolution = cat.CreateEntry<float>("Resolution", 1.1f, "Render scale (Fixed) or the highest render scale (Auto), 0.5..2", (string)null, false, false, (ValueValidator)null, (string)null);
			minResolution = cat.CreateEntry<float>("MinResolution", 0.8f, "Lowest render scale in Auto mode", (string)null, false, false, (ValueValidator)null, (string)null);
			msaa = cat.CreateEntry<string>("MSAA", "Game", "Game, Off, X2, X4, X8", (string)null, false, false, (ValueValidator)null, (string)null);
			shadows = cat.CreateEntry<string>("Shadows", "Game", "Game, Low, Medium, High, Ultra", (string)null, false, false, (ValueValidator)null, (string)null);
			ao = cat.CreateEntry<string>("AmbientOcclusion", "Game", "Game, Off, Low, Medium, High, UltraGI", (string)null, false, false, (ValueValidator)null, (string)null);
			ssr = cat.CreateEntry<string>("Reflections", "Game", "Screen-space reflections: Game, Off, On, High", (string)null, false, false, (ValueValidator)null, (string)null);
			tex = cat.CreateEntry<string>("Textures", "AF16", "Game, AF16, Sharp, UltraSharp", (string)null, false, false, (ValueValidator)null, (string)null);
			detail = cat.CreateEntry<string>("DetailDistance", "Normal", "LOD distance: Game, Near, Normal, Far, Ultra", (string)null, false, false, (ValueValidator)null, (string)null);
			sharpen = cat.CreateEntry<float>("Sharpen", 0f, "FSR sharpening 0..1 (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null);
			bloom = cat.CreateEntry<string>("Bloom", "Normal", "Game, Off, Soft, Normal, Strong", (string)null, false, false, (ValueValidator)null, (string)null);
			bloomQuality = cat.CreateEntry<string>("BloomQuality", "Medium", "Game, Low, Medium, High, Ultra", (string)null, false, false, (ValueValidator)null, (string)null);
			lensFlare = cat.CreateEntry<bool>("LensFlare", false, "", (string)null, false, false, (ValueValidator)null, (string)null);
			glare = cat.CreateEntry<bool>("Glare", false, "Anamorphic light streaks", (string)null, false, false, (ValueValidator)null, (string)null);
			lensDirt = cat.CreateEntry<bool>("LensDirt", false, "", (string)null, false, false, (ValueValidator)null, (string)null);
			tonemap = cat.CreateEntry<string>("Tonemapping", "Game", "Game, Neutral, ACES, Off", (string)null, false, false, (ValueValidator)null, (string)null);
			exposure = cat.CreateEntry<float>("Exposure", 0f, "EV, -2..2", (string)null, false, false, (ValueValidator)null, (string)null);
			contrast = cat.CreateEntry<float>("Contrast", 5f, "-50..50", (string)null, false, false, (ValueValidator)null, (string)null);
			saturation = cat.CreateEntry<float>("Saturation", 5f, "-50..50", (string)null, false, false, (ValueValidator)null, (string)null);
			temperature = cat.CreateEntry<float>("Temperature", 0f, "-50..50", (string)null, false, false, (ValueValidator)null, (string)null);
			vignette = cat.CreateEntry<float>("Vignette", 0.12f, "0..0.6", (string)null, false, false, (ValueValidator)null, (string)null);
			chroma = cat.CreateEntry<float>("ChromaticAberration", 0f, "0..1", (string)null, false, false, (ValueValidator)null, (string)null);
			grain = cat.CreateEntry<float>("FilmGrain", 0f, "0..1", (string)null, false, false, (ValueValidator)null, (string)null);
			godRays = cat.CreateEntry<string>("GodRays", "Game", "Volumetric light: Game, Off, Normal, Strong", (string)null, false, false, (ValueValidator)null, (string)null);
			weather = cat.CreateEntry<string>("Weather", "Level", "Level, Sunny, Clear, Cloudy, Overcast, Fog, Rain, Storm, Snow, Sunset, Night", (string)null, false, false, (ValueValidator)null, (string)null);
			weatherIntensity = cat.CreateEntry<float>("WeatherIntensity", 1f, "0.25..1.5", (string)null, false, false, (ValueValidator)null, (string)null);
			weatherSound = cat.CreateEntry<bool>("WeatherSound", true, "Rain, wind and thunder sounds", (string)null, false, false, (ValueValidator)null, (string)null);
			weatherVolume = cat.CreateEntry<float>("WeatherVolume", 0.8f, "0..1", (string)null, false, false, (ValueValidator)null, (string)null);
			lightning = cat.CreateEntry<bool>("Lightning", true, "Lightning in storms", (string)null, false, false, (ValueValidator)null, (string)null);
			loading = false;
		}

		private static T E<T>(MelonPreferences_Entry<string> e, T def) where T : struct, Enum
		{
			if (!Enum.TryParse<T>(e.Value, out var result))
			{
				return def;
			}
			return result;
		}

		private static void SetE<T>(MelonPreferences_Entry<string> e, T v, bool custom = true) where T : struct, Enum
		{
			e.Value = v.ToString();
			Touch(custom);
		}

		private static void Touch(bool custom)
		{
			if (!loading)
			{
				if (custom && !Presets.Applying && Preset != Preset.Custom)
				{
					preset.Value = Preset.Custom.ToString();
				}
				if (!Presets.Applying)
				{
					MelonPreferences.Save();
					Settings.Changed?.Invoke();
				}
			}
		}

		private static float Clamp(float v, float lo, float hi)
		{
			return Math.Clamp(v, lo, hi);
		}

		public static void Save()
		{
			MelonPreferences.Save();
			Settings.Changed?.Invoke();
		}
	}
	public struct WeatherDef
	{
		public Grade grade;

		public float fog;

		public float volExt;

		public float skyAlpha;

		public float coverage;

		public float cloudAlpha;

		public float softness;

		public float stars;

		public float sun;

		public float sunTintAmount;

		public float rain;

		public float snow;

		public float wind;

		public float lightning;

		public float useCube;

		public Color fogColor;

		public Color albedo;

		public Color zenith;

		public Color horizon;

		public Color ground;

		public Color cloud;

		public Color shade;

		public Color sunGlow;

		public Color sunTint;

		public static WeatherDef Lerp(WeatherDef a, WeatherDef b, float t)
		{
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			return new WeatherDef
			{
				grade = Grade.Lerp(a.grade, b.grade, t),
				fog = Mathf.Lerp(a.fog, b.fog, t),
				volExt = Mathf.Lerp(a.volExt, b.volExt, t),
				skyAlpha = Mathf.Lerp(a.skyAlpha, b.skyAlpha, t),
				coverage = Mathf.Lerp(a.coverage, b.coverage, t),
				cloudAlpha = Mathf.Lerp(a.cloudAlpha, b.cloudAlpha, t),
				softness = Mathf.Lerp(a.softness, b.softness, t),
				stars = Mathf.Lerp(a.stars, b.stars, t),
				sun = Mathf.Lerp(a.sun, b.sun, t),
				sunTintAmount = Mathf.Lerp(a.sunTintAmount, b.sunTintAmount, t),
				rain = Mathf.Lerp(a.rain, b.rain, t),
				snow = Mathf.Lerp(a.snow, b.snow, t),
				wind = Mathf.Lerp(a.wind, b.wind, t),
				lightning = Mathf.Lerp(a.lightning, b.lightning, t),
				useCube = Mathf.Lerp(a.useCube, b.useCube, t),
				fogColor = Color.Lerp(a.fogColor, b.fogColor, t),
				albedo = Color.Lerp(a.albedo, b.albedo, t),
				zenith = Color.Lerp(a.zenith, b.zenith, t),
				horizon = Color.Lerp(a.horizon, b.horizon, t),
				ground = Color.Lerp(a.ground, b.ground, t),
				cloud = Color.Lerp(a.cloud, b.cloud, t),
				shade = Color.Lerp(a.shade, b.shade, t),
				sunGlow = Color.Lerp(a.sunGlow, b.sunGlow, t),
				sunTint = Color.Lerp(a.sunTint, b.sunTint, t)
			};
		}
	}
	public static class Weather
	{
		private const float Transition = 5f;

		private const float RainHeight = 12f;

		private const float SnowHeight = 8f;

		private const int RoofMask = -2147482543;

		private static WeatherType target = WeatherType.Level;

		private static WeatherDef from;

		private static WeatherDef to;

		private static WeatherDef cur;

		private static float t = 1f;

		private static float intensity = -1f;

		private static bool started;

		private static bool levelCaptured;

		private static bool lvFog;

		private static FogMode lvFogMode;

		private static float lvFogDensity;

		private static Color lvFogColor;

		private static Light sun;

		private static float sunIntensity;

		private static Color sunColor;

		private static GameObject root;

		private static GameObject dome;

		private static GameObject rainGo;

		private static GameObject snowGo;

		private static GameObject audioGo;

		private static GameObject thunderGo;

		private static GameObject boltGo;

		private static Material domeMat;

		private static ParticleSystem rainPs;

		private static ParticleSystem snowPs;

		private static float rainBase = 4000f;

		private static float snowBase = 1100f;

		private static AudioSource rainA;

		private static AudioSource rainB;

		private static AudioSource windSrc;

		private static AudioSource thunderSrc;

		private static AudioLowPassFilter rainLp;

		private static AudioLowPassFilter thunderLp;

		private static AudioClip[] thunderClips;

		private static Light bolt;

		private static Cubemap cube;

		private static Il2CppStructArray<Color> cubePx;

		private static float cubeAt = -10f;

		private static Vector3 lastHead;

		private static Vector3 headVel;

		private static float indoor;

		private static float indoorTarget;

		private static float roofCheckAt;

		private static float roofHeight = -1f;

		private static float nextStrike = 8f;

		private static float strikeAt = -10f;

		private static float strikePower;

		private static readonly List<(float at, AudioClip clip, float vol)> pendingThunder = new List<(float, AudioClip, float)>();

		private static float flash;

		public static bool Active
		{
			get
			{
				if (Settings.Enabled)
				{
					if (target == WeatherType.Level)
					{
						return t < 1f;
					}
					return true;
				}
				return false;
			}
		}

		public static Grade Grade
		{
			get
			{
				//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)
				if (!Active)
				{
					return new Grade
					{
						filter = Color.white
					};
				}
				return cur.grade;
			}
		}

		public static float Flash
		{
			get
			{
				if (!Active)
				{
					return 0f;
				}
				return flash;
			}
		}

		public static float VolumetricFog
		{
			get
			{
				if (!Active || !(cur.volExt > 0.0005f))
				{
					return 0f;
				}
				return 1f / cur.volExt;
			}
		}

		public static Color FogAlbedo => cur.albedo;

		public static Cubemap SkyCube
		{
			get
			{
				if (!Active || !(cur.useCube > 0.5f))
				{
					return null;
				}
				return cube;
			}
		}

		public static bool Animating
		{
			get
			{
				if (Active)
				{
					if (!(t < 1f) && !(flash > 0f))
					{
						return Time.time - strikeAt < 1f;
					}
					return true;
				}
				return false;
			}
		}

		private static Color C(float r, float g, float b)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return new Color(r, g, b, 1f);
		}

		private static WeatherDef Neutral()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			return new WeatherDef
			{
				grade = new Grade
				{
					filter = Color.white
				},
				fog = ((lvFog && (int)lvFogMode == 3) ? lvFogDensity : 0f),
				fogColor = lvFogColor,
				albedo = Color.white,
				zenith = C(0.4f, 0.5f, 0.65f),
				horizon = lvFogColor,
				ground = lvFogColor,
				cloud = Color.white,
				shade = C(0.5f, 0.5f, 0.5f),
				sunTint = Color.white,
				sun = 1f,
				softness = 0.2f
			};
		}

		private static WeatherDef Def(WeatherType w)
		{
			//IL_0092: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unkno