Decompiled source of DeepWater v0.15.3

DeepWater.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.PostProcessing;
using UnityEngine.Rendering;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DeepWater
{
	internal sealed class Breath : MonoBehaviour
	{
		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<bool> _noUnderwaterRegen;

		private static ConfigEntry<bool> _skills;

		private static ConfigEntry<float> _baseBreath;

		private static ConfigEntry<float> _maxBreath;

		internal static readonly SkillType BreathSkill = (SkillType)StringExtensionMethods.GetStableHashCode("VoxelTerrain.BreathHold");

		internal static float Value = -1f;

		internal static bool HeadUnder;

		private float _drownTimer;

		private float _breathSkillTimer;

		private float _hideTimer;

		private static SkillDef _breathDef;

		private static readonly FieldRef<Player, float> _stamina = AccessTools.FieldRefAccess<Player, float>("m_stamina");

		private static float _staminaBefore;

		private static ConfigEntry<float> _swimCost;

		private static ConfigEntry<float> _fastSwimCost;

		private static ConfigEntry<float> _fastSwimSpeed;

		private static readonly FieldRef<Character, bool> _run = AccessTools.FieldRefAccess<Character, bool>("m_run");

		private static float _swimStaminaBefore;

		private static float _savedSwimSpeed = -1f;

		internal static bool FastSwim;

		private static Action<Player, Vector3, float> _onSwimming;

		private GameObject _bar;

		private RectTransform _barRoot;

		private GuiBar[] _bars;

		private Animator _anim;

		private Component _text;

		private PropertyInfo _textProp;

		private bool _barFailed;

		private static readonly int s_visible = Animator.StringToHash("Visible");

		private static readonly FieldRef<Hud, float> _border = AccessTools.FieldRefAccess<Hud, float>("m_staminaBarBorderBuffer");

		public static void Bind(ConfigFile cfg, Harmony harmony)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01b2: Expected O, but got Unknown
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: 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_020e: Expected O, but got Unknown
			//IL_020e: Expected O, but got Unknown
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Expected O, but got Unknown
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_0313: Expected O, but got Unknown
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			_enabled = cfg.Bind<bool>("Gameplay", "HoldBreath", true, "Under water you hold your breath: when it runs out you drown (damage every second). It comes back at the surface.");
			_baseBreath = cfg.Bind<float>("Gameplay", "BreathSeconds", 30f, new ConfigDescription("How long you can hold your breath at skill 0 (s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 600f), Array.Empty<object>()));
			_maxBreath = cfg.Bind<float>("Gameplay", "BreathSecondsAtMaxSkill", 90f, new ConfigDescription("How long you can hold your breath at skill 100 (s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 1200f), Array.Empty<object>()));
			_noUnderwaterRegen = cfg.Bind<bool>("Gameplay", "NoStaminaRegenUnderWater", true, "With the head under water stamina doesn't come back, also standing on the bottom (vanilla: full regeneration as on land).");
			_skills = cfg.Bind<bool>("Gameplay", "BreathSkill", true, "Skill 'Breath holding': rises under water, longer breath.");
			_swimCost = cfg.Bind<float>("Gameplay", "SwimStaminaFactor", 0.5f, new ConfigDescription("Stamina cost of normal swimming, times vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			_fastSwimCost = cfg.Bind<float>("Gameplay", "FastSwimStaminaFactor", 2f, new ConfigDescription("Stamina cost of fast swimming (hold Run), times vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			_fastSwimSpeed = cfg.Bind<float>("Gameplay", "FastSwimSpeed", 1.6f, new ConfigDescription("Fast swimming (hold Run) speed, times normal swimming. 1 = off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "OnSwimming", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "OnSwimmingPrefix", (Type[])null), new HarmonyMethod(typeof(Breath), "OnSwimmingPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "SpeedPrefix", (Type[])null)
			{
				priority = 800
			}, new HarmonyMethod(typeof(Breath), "SpeedPostfix", (Type[])null)
			{
				priority = 0
			}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Skills), "IsSkillValid", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "IsSkillValidPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Skills), "GetSkillDef", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Breath), "GetSkillDefPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "LanguagePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "UpdateStats", new Type[1] { typeof(float) }, (Type[])null), new HarmonyMethod(typeof(Breath), "StatsPrefix", (Type[])null), new HarmonyMethod(typeof(Breath), "StatsPostfix", (Type[])null)
			{
				priority = 0
			}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Breath), "SwimmingPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool Ours(SkillType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return t == BreathSkill;
		}

		private static void IsSkillValidPostfix(SkillType type, ref bool __result)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (!__result && Ours(type))
			{
				__result = true;
			}
		}

		private static bool GetSkillDefPrefix(SkillType type, ref SkillDef __result)
		{
			//IL_0000: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!Ours(type))
			{
				return true;
			}
			if (_breathDef == null)
			{
				_breathDef = new SkillDef
				{
					m_skill = BreathSkill,
					m_increseStep = 1f
				};
			}
			_breathDef.m_description = (Russian() ? "Дольше задерживать дыхание под водой." : "Hold your breath longer under water.");
			if ((Object)(object)_breathDef.m_icon == (Object)null)
			{
				_breathDef.m_icon = FindIcon();
			}
			__result = _breathDef;
			return false;
		}

		private static Sprite FindIcon()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			StatusEffect statusEffect = instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Wet"));
			if ((Object)(object)statusEffect != (Object)null && (Object)(object)statusEffect.m_icon != (Object)null)
			{
				return statusEffect.m_icon;
			}
			Player localPlayer = Player.m_localPlayer;
			Skills val = (((Object)(object)localPlayer != (Object)null) ? ((Character)localPlayer).GetSkills() : null);
			if ((Object)(object)val != (Object)null)
			{
				foreach (SkillDef skill in val.m_skills)
				{
					if ((int)skill.m_skill == 103)
					{
						return skill.m_icon;
					}
				}
			}
			return null;
		}

		private static bool Russian()
		{
			return PlatformPrefs.GetString("language", "English") == "Russian";
		}

		private static void LanguagePostfix(Localization __instance)
		{
			AddWords(__instance);
		}

		private static void AddWords(Localization loc)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (loc != null)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);
				if (!(methodInfo == null))
				{
					methodInfo.Invoke(loc, new object[2]
					{
						"skill_" + ((object)BreathSkill/*cast due to .constrained prefix*/).ToString().ToLower(),
						Russian() ? "Задержка дыхания" : "Breath holding"
					});
				}
			}
		}

		private static void StatsPrefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				_staminaBefore = _stamina.Invoke(__instance);
			}
		}

		private static void StatsPostfix(Player __instance)
		{
			if (_noUnderwaterRegen.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (HeadUnder || SwimItems.Underwater))
			{
				ref float reference = ref _stamina.Invoke(__instance);
				if (reference > _staminaBefore)
				{
					reference = _staminaBefore;
				}
			}
		}

		private static void SpeedPrefix(Character __instance)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)__instance;
			int fastSwim;
			if (_fastSwimSpeed.Value > 1.001f && _run.Invoke(__instance))
			{
				Vector3 moveDir = ((Character)val).GetMoveDir();
				if (((Vector3)(ref moveDir)).sqrMagnitude > 0.01f)
				{
					fastSwim = (((Character)val).HaveStamina(0f) ? 1 : 0);
					goto IL_0057;
				}
			}
			fastSwim = 0;
			goto IL_0057;
			IL_0057:
			FastSwim = (byte)fastSwim != 0;
			if (FastSwim)
			{
				_savedSwimSpeed = __instance.m_swimSpeed;
				__instance.m_swimSpeed *= _fastSwimSpeed.Value;
			}
		}

		private static void SpeedPostfix(Character __instance)
		{
			if (!(_savedSwimSpeed < 0f) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				__instance.m_swimSpeed = _savedSwimSpeed;
				_savedSwimSpeed = -1f;
			}
		}

		private static void OnSwimmingPrefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				_swimStaminaBefore = _stamina.Invoke(__instance);
			}
		}

		private static void OnSwimmingPostfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				ref float reference = ref _stamina.Invoke(__instance);
				float num = _swimStaminaBefore - reference;
				if (!(num <= 0f))
				{
					reference = Mathf.Max(0f, _swimStaminaBefore - num * (FastSwim ? _fastSwimCost.Value : _swimCost.Value));
				}
			}
		}

		private static void SwimmingPostfix(Character __instance, float dt)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!_noUnderwaterRegen.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !__instance.IsOnGround() || (!HeadUnder && !SwimItems.Underwater))
			{
				return;
			}
			Player val = (Player)__instance;
			Vector3 arg = ((Character)val).GetMoveDir() * ((Character)val).m_swimSpeed;
			if (!(((Vector3)(ref arg)).magnitude <= 0.1f))
			{
				if (_onSwimming == null)
				{
					_onSwimming = AccessTools.MethodDelegate<Action<Player, Vector3, float>>(AccessTools.Method(typeof(Player), "OnSwimming", (Type[])null, (Type[])null), (object)null, false);
				}
				_onSwimming(val, arg, dt);
			}
		}

		public static float MaxBreath(Player p)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			float num = ((_skills.Value && (Object)(object)p != (Object)null) ? ((Character)p).GetSkillFactor(BreathSkill) : 0f);
			return Mathf.Max(1f, Mathf.Lerp(_baseBreath.Value, Mathf.Max(_baseBreath.Value, _maxBreath.Value), num));
		}

		private void Update()
		{
			//IL_005c: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				HeadUnder = false;
				Value = -1f;
				ShowBar(visible: false, 0f, 0f, 1f);
				return;
			}
			float deltaTime = Time.deltaTime;
			float liquidLevel = ((Character)localPlayer).GetLiquidLevel();
			HeadUnder = ((Character)localPlayer).InWater() && liquidLevel > -1000f && ((Character)localPlayer).GetHeadPoint().y < liquidLevel - 0.05f;
			float num = MaxBreath(localPlayer);
			if (Value < 0f)
			{
				Value = num;
			}
			if (_enabled.Value && HeadUnder && !((Character)localPlayer).InGodMode() && !((Character)localPlayer).InGhostMode())
			{
				Vector3 moveDir = ((Character)localPlayer).GetMoveDir();
				bool flag = ((Vector3)(ref moveDir)).sqrMagnitude > 0.01f || ZInput.GetButton("Jump") || ZInput.GetButton("Crouch");
				Value = Mathf.Max(0f, Value - deltaTime * (flag ? 1.5f : 1.05f));
				if (Value <= 0f)
				{
					_drownTimer += deltaTime;
					if (_drownTimer > 1f)
					{
						_drownTimer = 0f;
						HitData val = new HitData();
						val.m_damage.m_damage = Mathf.Ceil(((Character)localPlayer).GetMaxHealth() / 10f);
						val.m_point = ((Character)localPlayer).GetCenterPoint();
						val.m_dir = Vector3.down;
						val.m_hitType = (HitType)4;
						((Character)localPlayer).Damage(val);
						localPlayer.m_drownEffects.Create(((Character)localPlayer).GetHeadPoint(), ((Component)localPlayer).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
					}
				}
				if (_skills.Value)
				{
					_breathSkillTimer += deltaTime;
					if (_breathSkillTimer > 1f)
					{
						_breathSkillTimer = 0f;
						((Character)localPlayer).RaiseSkill(BreathSkill, (Value < num * 0.25f) ? 0.6f : 0.4f);
					}
				}
			}
			else
			{
				_drownTimer = 0f;
				if (!HeadUnder)
				{
					Value = Mathf.Min(num, Value + deltaTime * Mathf.Max(num / 2f, 16f));
				}
			}
			Value = Mathf.Min(Value, num);
			bool flag2 = _enabled.Value && (HeadUnder || Value < num - 0.01f);
			_hideTimer = (flag2 ? 0f : (_hideTimer + deltaTime));
			ShowBar(_hideTimer < 1f, Value, num, deltaTime);
		}

		private void ShowBar(bool visible, float value, float max, float dt)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_bar == (Object)null && (!visible || _barFailed || !MakeBar()))
			{
				return;
			}
			if ((Object)(object)_anim != (Object)null && ((Behaviour)_anim).isActiveAndEnabled)
			{
				_anim.SetBool(s_visible, visible);
			}
			else
			{
				_bar.SetActive(visible);
			}
			if (visible || (!((Object)(object)_anim == (Object)null) && ((Behaviour)_anim).isActiveAndEnabled))
			{
				if (!_bar.activeSelf)
				{
					_bar.SetActive(true);
				}
				Hud instance = Hud.instance;
				float num = Mathf.Clamp(max * 3f, 60f, 400f);
				_barRoot.SetSizeWithCurrentAnchors((Axis)0, num + (((Object)(object)instance != (Object)null) ? _border.Invoke(instance) : 0f));
				GuiBar[] bars = _bars;
				foreach (GuiBar obj in bars)
				{
					obj.SetWidth(num);
					obj.SetValue((max > 0f) ? (value / max) : 0f);
				}
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_staminaBar2Root != (Object)null)
				{
					_barRoot.anchoredPosition = instance.m_staminaBar2Root.anchoredPosition + new Vector2(0f, 34f);
				}
				if ((Object)(object)_text != (Object)null && _textProp != null)
				{
					_textProp.SetValue(_text, Mathf.CeilToInt(value).ToString());
				}
			}
		}

		private bool MakeBar()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0082: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_eitrBarRoot == (Object)null || (Object)(object)instance.m_staminaBar2Root == (Object)null)
			{
				return false;
			}
			try
			{
				_bar = Object.Instantiate<GameObject>(((Component)instance.m_eitrBarRoot).gameObject, ((Transform)instance.m_staminaBar2Root).parent, false);
				((Object)_bar).name = "DeepWater breath bar";
				_barRoot = (RectTransform)_bar.transform;
				_barRoot.anchorMin = instance.m_staminaBar2Root.anchorMin;
				_barRoot.anchorMax = instance.m_staminaBar2Root.anchorMax;
				_barRoot.pivot = instance.m_staminaBar2Root.pivot;
				_bars = _bar.GetComponentsInChildren<GuiBar>(true);
				Color val = default(Color);
				((Color)(ref val))..ctor(0.35f, 0.75f, 1f, 1f);
				for (int i = 0; i < _bars.Length; i++)
				{
					_bars[i].SetColor((Color)((i == 0) ? val : new Color(val.r * 0.6f, val.g * 0.6f, val.b * 0.7f, 1f)));
				}
				_anim = _bar.GetComponentInChildren<Animator>(true);
				Component[] componentsInChildren = _bar.GetComponentsInChildren<Component>(true);
				foreach (Component val2 in componentsInChildren)
				{
					if (!((Object)(object)val2 == (Object)null) && ((object)val2).GetType().Name.StartsWith("TextMeshPro"))
					{
						_text = val2;
						_textProp = ((object)val2).GetType().GetProperty("text");
						break;
					}
				}
				List<string> list = new List<string>();
				Transform[] componentsInChildren2 = _bar.GetComponentsInChildren<Transform>(true);
				foreach (Transform val3 in componentsInChildren2)
				{
					list.Add(((Object)val3).name);
				}
				Plugin.Log.LogInfo((object)($"Breath bar from the eitr bar: {_bars.Length} bars, animator {(Object)(object)_anim != (Object)null}, text {(Object)(object)_text != (Object)null}; " + "parts: " + string.Join(", ", list)));
				return _bars.Length != 0;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Breath bar: " + ex.Message));
				if ((Object)(object)_bar != (Object)null)
				{
					Object.Destroy((Object)(object)_bar);
				}
				_bar = null;
				_barFailed = true;
				return false;
			}
		}
	}
	internal sealed class Bubbles
	{
		private sealed class State
		{
			public bool HeadUnder;

			public float NextBreath;

			public float TrailCarry;
		}

		private const float Range = 40f;

		private ParticleSystem _ps;

		private readonly Dictionary<Player, State> _state = new Dictionary<Player, State>();

		private readonly List<Player> _players = new List<Player>();

		private readonly List<Player> _gone = new List<Player>();

		private Particle[] _buf = (Particle[])(object)new Particle[256];

		private Color _tint = new Color(0.4f, 0.52f, 0.55f, 0.5f);

		public void Update(Shader additive)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)additive == (Object)null)
			{
				return;
			}
			_players.Clear();
			Player.GetPlayersInRange(((Component)localPlayer).transform.position, 40f, _players);
			bool flag = false;
			foreach (Player player in _players)
			{
				flag |= UpdatePlayer(player, additive);
			}
			if (_state.Count > _players.Count)
			{
				_gone.Clear();
				foreach (Player key in _state.Keys)
				{
					if ((Object)(object)key == (Object)null || !_players.Contains(key))
					{
						_gone.Add(key);
					}
				}
				foreach (Player item in _gone)
				{
					_state.Remove(item);
				}
			}
			if ((Object)(object)_ps != (Object)null && _ps.particleCount > 0)
			{
				CullAboveSurface();
			}
			if (!flag && (Object)(object)_ps != (Object)null && _ps.particleCount == 0 && ((Component)_ps).gameObject.activeSelf)
			{
				((Component)_ps).gameObject.SetActive(false);
			}
		}

		private void CullAboveSurface()
		{
			//IL_004d: 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_0053: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			int particleCount = _ps.particleCount;
			if (_buf.Length < particleCount)
			{
				_buf = (Particle[])(object)new Particle[Mathf.NextPowerOfTwo(particleCount)];
			}
			particleCount = _ps.GetParticles(_buf, particleCount);
			int num = 0;
			for (int i = 0; i < particleCount; i++)
			{
				Vector3 position = ((Particle)(ref _buf[i])).position;
				float liquidLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0);
				if (!(liquidLevel > -9999f) || !(position.y > liquidLevel - 0.03f))
				{
					_buf[num++] = _buf[i];
				}
			}
			if (num != particleCount)
			{
				_ps.SetParticles(_buf, num);
			}
		}

		private bool UpdatePlayer(Player p, Shader additive)
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: 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_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)p == (Object)null || ((Character)p).IsDead())
			{
				return false;
			}
			Vector3 headPoint = ((Character)p).GetHeadPoint();
			float liquidLevel = Floating.GetLiquidLevel(headPoint, 1f, (LiquidType)0);
			if (!_state.TryGetValue(p, out var value))
			{
				Dictionary<Player, State> state = _state;
				State obj = new State
				{
					NextBreath = Time.time + Random.Range(0.5f, 2f)
				};
				value = obj;
				state[p] = obj;
			}
			if (!(liquidLevel > -9999f) || !(headPoint.y < liquidLevel - 0.05f))
			{
				value.HeadUnder = false;
				return false;
			}
			float num = Mathf.Lerp(1f, 0.5f, Mathf.Clamp01((liquidLevel - headPoint.y) / 25f)) * Mathf.Lerp(0.12f, 1f, Mathf.InverseLerp(0.3f, 1f, Underwater.Daylight));
			_tint = new Color(0.6f * num, 0.75f * num, 0.8f * num, 0.75f);
			if ((Object)(object)_ps == (Object)null && (Object)(object)(_ps = Create(additive)) == (Object)null)
			{
				return false;
			}
			if (!((Component)_ps).gameObject.activeSelf)
			{
				((Component)_ps).gameObject.SetActive(true);
				_ps.Play();
			}
			if ((Object)(object)p == (Object)(object)Player.m_localPlayer)
			{
				((Component)_ps).transform.position = headPoint;
			}
			Vector3 forward = ((Component)p).transform.forward;
			Vector3 velocity = ((Character)p).GetVelocity();
			if (!value.HeadUnder)
			{
				value.HeadUnder = true;
				Vector3 centerPoint = ((Character)p).GetCenterPoint();
				for (int i = 0; i < 28; i++)
				{
					Emit(centerPoint + Random.insideUnitSphere * 0.45f, liquidLevel, velocity * 0.2f, Random.Range(0.05f, 0.16f));
				}
				value.NextBreath = Time.time + Random.Range(1.5f, 3f);
			}
			if (Time.time >= value.NextBreath)
			{
				value.NextBreath = Time.time + Random.Range(2.5f, 4.5f);
				Vector3 val = headPoint + forward * 0.14f - Vector3.up * 0.06f;
				int num2 = Random.Range(7, 14);
				for (int j = 0; j < num2; j++)
				{
					Emit(val + Random.insideUnitSphere * 0.04f - Vector3.up * ((float)j * 0.03f), liquidLevel, forward * Random.Range(0.1f, 0.35f), Random.Range(0.03f, 0.11f));
				}
			}
			float magnitude = ((Vector3)(ref velocity)).magnitude;
			if (magnitude > 0.4f)
			{
				value.TrailCarry += Time.deltaTime * Mathf.Min(magnitude, 6f) * 5f;
				Vector3 centerPoint2 = ((Character)p).GetCenterPoint();
				Vector3 val2 = velocity / magnitude;
				while (value.TrailCarry >= 1f)
				{
					value.TrailCarry -= 1f;
					Vector3 pos = centerPoint2 + Random.insideUnitSphere * 0.35f - val2 * Random.Range(0f, 0.5f);
					Emit(pos, liquidLevel, -velocity * 0.08f, Random.Range(0.02f, 0.07f));
				}
			}
			return true;
		}

		private void Emit(Vector3 pos, float level, Vector3 push, float size)
		{
			//IL_002c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			size *= 0.7f;
			float num = Mathf.Lerp(0.5f, 1.1f, Mathf.InverseLerp(0.02f, 0.16f, size));
			float startLifetime = Mathf.Clamp((level - pos.y - 0.05f) / num, 0.15f, 7f);
			EmitParams val = default(EmitParams);
			((EmitParams)(ref val)).position = pos;
			((EmitParams)(ref val)).velocity = push + Vector3.up * num + Underwater.Current * 0.6f;
			((EmitParams)(ref val)).startSize = size;
			((EmitParams)(ref val)).startLifetime = startLifetime;
			((EmitParams)(ref val)).startColor = Color32.op_Implicit(_tint);
			((EmitParams)(ref val)).applyShapeToPosition = false;
			EmitParams val2 = val;
			_ps.Emit(val2, 1);
		}

		private static ParticleSystem Create(Shader additive)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_01e6: Expected O, but got Unknown
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DeepWater bubbles");
			Object.DontDestroyOnLoad((Object)(object)val);
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			val2.Stop(true, (ParticleSystemStopBehavior)0);
			MainModule main = val2.main;
			((MainModule)(ref main)).cullingMode = (ParticleSystemCullingMode)3;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).maxParticles = 1500;
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f);
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).enabled = false;
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).enabled = false;
			NoiseModule noise = val2.noise;
			((NoiseModule)(ref noise)).enabled = true;
			((NoiseModule)(ref noise)).strength = MinMaxCurve.op_Implicit(0.35f);
			((NoiseModule)(ref noise)).frequency = 1.4f;
			((NoiseModule)(ref noise)).scrollSpeed = MinMaxCurve.op_Implicit(0.6f);
			((NoiseModule)(ref noise)).quality = (ParticleSystemNoiseQuality)0;
			SizeOverLifetimeModule sizeOverLifetime = val2.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
			((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 0.8f, 1f, 1.35f));
			ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(1f, 0.08f),
				new GradientAlphaKey(0.9f, 0.85f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			Material val4 = new Material(additive)
			{
				name = "DeepWater bubble",
				mainTexture = (Texture)(object)BubbleTexture(),
				renderQueue = 3100
			};
			val4.SetColor("_TintColor", new Color(0.5f, 0.5f, 0.5f, 0.5f));
			((Renderer)component).sharedMaterial = val4;
			component.renderMode = (ParticleSystemRenderMode)0;
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			val2.Play();
			return val2;
		}

		private static Texture2D BubbleTexture()
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(24, 24, (TextureFormat)4, true)
			{
				name = "voxel bubble",
				wrapMode = (TextureWrapMode)1
			};
			Color[] array = (Color[])(object)new Color[576];
			for (int i = 0; i < 24; i++)
			{
				for (int j = 0; j < 24; j++)
				{
					float num = ((float)j + 0.5f) / 24f * 2f - 1f;
					float num2 = ((float)i + 0.5f) / 24f * 2f - 1f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					float num4 = Mathf.Exp(0f - Mathf.Pow((num3 - 0.7f) / 0.22f, 2f));
					float num5 = 0.25f * Mathf.Clamp01(1f - num3);
					float num6 = num + 0.3f;
					float num7 = num2 - 0.32f;
					float num8 = Mathf.Exp((0f - (num6 * num6 + num7 * num7)) / 0.05f);
					float num9 = Mathf.Clamp01(num4 * 0.8f + num5 + num8 * 0.7f) * Mathf.Clamp01((1f - num3) * 4f);
					array[i * 24 + j] = new Color(1f, 1f, 1f, num9);
				}
			}
			val.SetPixels(array);
			val.Apply(true);
			return val;
		}

		public void Destroy()
		{
			if ((Object)(object)_ps != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_ps).gameObject);
			}
			_ps = null;
			_state.Clear();
		}
	}
	internal sealed class Caustics
	{
		private struct Wave
		{
			public float Kx;

			public float Ky;

			public float Amp;

			public float Phase;

			public int Cycles;
		}

		private const int Frames = 120;

		private const int Size = 256;

		private Texture2D[] _frames;

		private Light _sun;

		private Texture _savedCookie;

		private float _savedCookieSize;

		private bool _applied;

		private ParticleSystem _rays;

		private float _phase;

		private float _wind = 0.3f;

		private Vector3 _drift;

		private volatile byte[][] _pixels;

		private bool _generating;

		public void Update(Camera cam, bool under, float level, float depth, Shader additive)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: 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)
			Light val = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.m_dirLight : null);
			if ((Object)(object)EnvMan.instance != (Object)null)
			{
				_wind = Mathf.MoveTowards(_wind, EnvMan.instance.GetWindIntensity(), Time.deltaTime * 0.1f);
			}
			if (!under || (Object)(object)val == (Object)null)
			{
				Restore();
				StopRays();
				return;
			}
			if (!Ready())
			{
				UpdateRays(cam, level, depth, val, additive);
				return;
			}
			if (!_applied || (Object)(object)val != (Object)(object)_sun)
			{
				Restore();
				_sun = val;
				_savedCookie = val.cookie;
				_savedCookieSize = val.cookieSize;
				_applied = true;
			}
			float wind = _wind;
			Vector3 windDir = EnvMan.instance.GetWindDir();
			_phase += Time.deltaTime * Mathf.Lerp(7f, 20f, wind * wind);
			_drift += new Vector3(windDir.x, 0f, windDir.z) * (Time.deltaTime * Mathf.Lerp(0.1f, 0.8f, wind));
			if (((Vector3)(ref _drift)).sqrMagnitude > 1000000f)
			{
				_drift = Vector3.zero;
			}
			if (_phase > 600000f)
			{
				_phase -= 600000f;
			}
			val.cookie = Current();
			val.cookieSize = 8f;
			((Component)val).transform.position = -((Component)val).transform.forward * 3000f + _drift;
			UpdateRays(cam, level, depth, val, additive);
		}

		public void Prewarm()
		{
			if (_frames == null)
			{
				Ready();
			}
		}

		public void Suspend()
		{
			if (_applied && (Object)(object)_sun != (Object)null)
			{
				_sun.cookie = _savedCookie;
			}
		}

		public void Resume()
		{
			if (_applied && (Object)(object)_sun != (Object)null && _frames != null)
			{
				_sun.cookie = Current();
			}
		}

		private Texture Current()
		{
			return (Texture)(object)_frames[(int)_phase % 120];
		}

		public void Restore()
		{
			if (_applied)
			{
				if ((Object)(object)_sun != (Object)null)
				{
					_sun.cookie = _savedCookie;
					_sun.cookieSize = _savedCookieSize;
				}
				_applied = false;
			}
		}

		private void StartGenerate()
		{
			_generating = true;
			ThreadPool.QueueUserWorkItem(delegate
			{
				try
				{
					_pixels = Build();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Caustics generation failed: " + ex.Message));
				}
			});
		}

		private bool Ready()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			if (_frames != null)
			{
				return true;
			}
			if (!_generating)
			{
				StartGenerate();
			}
			byte[][] pixels = _pixels;
			if (pixels == null)
			{
				return false;
			}
			_frames = (Texture2D[])(object)new Texture2D[120];
			for (int i = 0; i < 120; i++)
			{
				Texture2D val = new Texture2D(256, 256, (TextureFormat)1, true)
				{
					name = "voxel caustics " + i,
					wrapMode = (TextureWrapMode)0,
					filterMode = (FilterMode)2,
					anisoLevel = 2
				};
				val.SetPixelData<byte>(pixels[i], 0, 0);
				val.Apply(true, true);
				_frames[i] = val;
			}
			_pixels = null;
			Plugin.Log.LogInfo((object)$"Caustics: {120} frames ({256}x{256}) generated");
			return true;
		}

		private static byte[][] Build()
		{
			Wave[] array = new Wave[8]
			{
				new Wave
				{
					Kx = 3f,
					Ky = 1f,
					Amp = 1f,
					Phase = 0.3f,
					Cycles = 1
				},
				new Wave
				{
					Kx = 4f,
					Ky = -1f,
					Amp = 0.75f,
					Phase = 1.9f,
					Cycles = 2
				},
				new Wave
				{
					Kx = 5f,
					Ky = 2f,
					Amp = 0.45f,
					Phase = 4.1f,
					Cycles = -2
				},
				new Wave
				{
					Kx = 2f,
					Ky = -3f,
					Amp = 0.55f,
					Phase = 2.7f,
					Cycles = 1
				},
				new Wave
				{
					Kx = 7f,
					Ky = 1f,
					Amp = 0.22f,
					Phase = 5.3f,
					Cycles = 3
				},
				new Wave
				{
					Kx = 1f,
					Ky = 4f,
					Amp = 0.3f,
					Phase = 0.9f,
					Cycles = -1
				},
				new Wave
				{
					Kx = 6f,
					Ky = -4f,
					Amp = 0.14f,
					Phase = 3.3f,
					Cycles = 3
				},
				new Wave
				{
					Kx = 9f,
					Ky = 3f,
					Amp = 0.08f,
					Phase = 1.4f,
					Cycles = -3
				}
			};
			byte[][] array2 = new byte[120][];
			float[] array3 = new float[65536];
			float[] array4 = new float[65536];
			float num = 3.0625f;
			for (int i = 0; i < 120; i++)
			{
				Array.Clear(array3, 0, array3.Length);
				float num2 = (float)i / 120f;
				for (int j = 0; j < 448; j++)
				{
					for (int k = 0; k < 448; k++)
					{
						float num3 = ((float)k + 0.5f) / 448f;
						float num4 = ((float)j + 0.5f) / 448f;
						float num5 = 0f;
						float num6 = 0f;
						Wave[] array5 = array;
						for (int l = 0; l < array5.Length; l++)
						{
							Wave wave = array5[l];
							float num7 = wave.Amp * Mathf.Cos((float)Math.PI * 2f * (wave.Kx * num3 + wave.Ky * num4 + (float)wave.Cycles * num2) + wave.Phase) * ((float)Math.PI * 2f);
							num5 += num7 * wave.Kx;
							num6 += num7 * wave.Ky;
						}
						float num8 = (num3 - num5 * 0.003f) * 256f - 0.5f;
						float num9 = (num4 - num6 * 0.003f) * 256f - 0.5f;
						int num10 = Mathf.FloorToInt(num8);
						int num11 = Mathf.FloorToInt(num9);
						float num12 = num8 - (float)num10;
						float num13 = num9 - (float)num11;
						int num14 = (num10 % 256 + 256) % 256;
						int num15 = (num14 + 1) % 256;
						int num16 = (num11 % 256 + 256) % 256;
						int num17 = (num16 + 1) % 256;
						array3[num16 * 256 + num14] += (1f - num12) * (1f - num13);
						array3[num16 * 256 + num15] += num12 * (1f - num13);
						array3[num17 * 256 + num14] += (1f - num12) * num13;
						array3[num17 * 256 + num15] += num12 * num13;
					}
				}
				for (int m = 0; m < 2; m++)
				{
					Blur(array3, array4, 3, horizontal: true);
					Blur(array4, array3, 3, horizontal: false);
				}
				byte[] array6 = new byte[65536];
				for (int n = 0; n < array3.Length; n++)
				{
					float num18 = array3[n] / num;
					float num19 = 0.4f + 0.6f * (1f - Mathf.Exp(-0.55f * num18));
					array6[n] = (byte)Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(num19) * 255f), 0, 255);
				}
				array2[i] = array6;
			}
			return array2;
		}

		private static void Blur(float[] src, float[] dst, int r, bool horizontal)
		{
			float num = 1f / (float)(2 * r + 1);
			for (int i = 0; i < 256; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					float num2 = 0f;
					for (int k = -r; k <= r; k++)
					{
						int num3 = (horizontal ? ((j + k + 256) % 256) : j);
						int num4 = (horizontal ? i : ((i + k + 256) % 256));
						num2 += src[num4 * 256 + num3];
					}
					dst[i * 256 + j] = num2 * num;
				}
			}
		}

		private void UpdateRays(Camera cam, float level, float depth, Light sun, Shader additive)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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_01c8: 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)
			Vector3 val = -((Component)sun).transform.forward;
			if ((Object)(object)additive == (Object)null || val.y < 0.1f || depth > 0.6f)
			{
				StopRays();
				return;
			}
			if ((Object)(object)_rays == (Object)null)
			{
				_rays = CreateRays(additive);
			}
			if (!((Object)(object)_rays == (Object)null))
			{
				Vector3 val2 = -val;
				Vector3 val3 = new Vector3(val2.x, 0f, val2.z) / 1.333f;
				Vector3 val4 = new Vector3(val3.x, 0f - Mathf.Sqrt(Mathf.Max(0.05f, 1f - ((Vector3)(ref val3)).sqrMagnitude)), val3.z);
				Vector3 normalized = ((Vector3)(ref val4)).normalized;
				Vector3 position = ((Component)cam).transform.position;
				((Component)_rays).transform.position = new Vector3(position.x, Mathf.Min(level - 1f, position.y + 10f), position.z);
				MainModule main = _rays.main;
				((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.01f);
				VelocityOverLifetimeModule velocityOverLifetime = _rays.velocityOverLifetime;
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true;
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)1;
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).x = MinMaxCurve.op_Implicit(normalized.x * 0.4f);
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).y = MinMaxCurve.op_Implicit(normalized.y * 0.4f);
				((VelocityOverLifetimeModule)(ref velocityOverLifetime)).z = MinMaxCurve.op_Implicit(normalized.z * 0.4f);
				float num = Mathf.Clamp01(val.y * 2f) * (1f - depth / 0.6f);
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.55f, 0.85f, 0.8f, 0.07f * num));
				if (!_rays.isEmitting)
				{
					_rays.Play();
				}
			}
		}

		private void StopRays()
		{
			if ((Object)(object)_rays != (Object)null && _rays.isEmitting)
			{
				_rays.Stop(true, (ParticleSystemStopBehavior)1);
			}
		}

		private static ParticleSystem CreateRays(Shader additive)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DeepWater god rays");
			Object.DontDestroyOnLoad((Object)(object)val);
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			val2.Stop(true, (ParticleSystemStopBehavior)0);
			MainModule main = val2.main;
			((MainModule)(ref main)).cullingMode = (ParticleSystemCullingMode)3;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(4f, 7f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(0.8f, 2.2f);
			((MainModule)(ref main)).maxParticles = 220;
			((MainModule)(ref main)).playOnAwake = false;
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(30f);
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)5;
			((ShapeModule)(ref shape)).scale = new Vector3(40f, 2f, 40f);
			ColorOverLifetimeModule colorOverLifetime = val2.colorOverLifetime;
			((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
			Gradient val3 = new Gradient();
			val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
			{
				new GradientColorKey(Color.white, 0f),
				new GradientColorKey(Color.white, 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(0f, 0f),
				new GradientAlphaKey(1f, 0.35f),
				new GradientAlphaKey(1f, 0.65f),
				new GradientAlphaKey(0f, 1f)
			});
			((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val3);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)1;
			component.lengthScale = 0f;
			component.velocityScale = 45f;
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = false;
			Material val4 = new Material(additive)
			{
				name = "DeepWater god ray",
				mainTexture = (Texture)(object)RayTexture(),
				renderQueue = 3100
			};
			val4.SetColor("_TintColor", new Color(0.5f, 0.5f, 0.5f, 0.5f));
			((Renderer)component).sharedMaterial = val4;
			return val2;
		}

		private static Texture2D RayTexture()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0021: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(32, 128, (TextureFormat)4, false)
			{
				name = "voxel ray",
				wrapMode = (TextureWrapMode)1
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = 1f - Mathf.Abs(((float)j + 0.5f) / 32f * 2f - 1f);
					float num2 = Mathf.Sin(((float)i + 0.5f) / 128f * (float)Math.PI);
					float num3 = Mathf.Pow(num, 2.5f) * num2;
					array[i * 32 + j] = new Color(1f, 1f, 1f, num3);
				}
			}
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		public void Destroy()
		{
			Restore();
			if ((Object)(object)_rays != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_rays).gameObject);
			}
			if (_frames == null)
			{
				return;
			}
			Texture2D[] frames = _frames;
			foreach (Texture2D val in frames)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	[BepInPlugin("moxy.deepwater", "DeepWater", "0.15.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "moxy.deepwater";

		public const string Version = "0.15.3";

		internal static ManualLogSource Log;

		private ConfigEntry<float> _seaDepth;

		private float _nextSeaDepth;

		private Harmony _harmony;

		private readonly HashSet<int> _seaDepthLogged = new HashSet<int>();

		private readonly float[] _seaDepthArr = new float[4];

		private static readonly FieldRef<WaterVolume, float[]> _wvDepth = AccessTools.FieldRefAccess<WaterVolume, float[]>("m_normalizedDepth");

		private static readonly FieldRef<WaterVolume, float> _wvOneDepth = AccessTools.FieldRefAccess<WaterVolume, float>("m_oneDepth");

		private static ManualLogSource Quiet(ManualLogSource real)
		{
			//IL_0018: 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_0030: Expected O, but got Unknown
			ManualLogSource val = new ManualLogSource(real.SourceName);
			val.LogEvent += delegate(object s, LogEventArgs e)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				if ((e.Level & 0xF) != 0)
				{
					real.Log(e.Level, e.Data);
				}
			};
			return val;
		}

		private void Awake()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			if (!((BaseUnityPlugin)this).Config.Bind<bool>("General", "DeveloperMode", false, "The developer's diagnostic log lines. Off: only warnings and errors are logged.").Value)
			{
				Log = Quiet(((BaseUnityPlugin)this).Logger);
			}
			_seaDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Water", "MinSeaDepthLook", 1f, new ConfigDescription("The game colours (and sizes the waves of) each 64 m water tile by the depth at its 4 corners: shore tiles turn brown without the blue wave pattern, with a hard edge to the next tile. Every tile is shaded at least this deep (0..1, 1 = like the open sea everywhere, no seams). -1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>()));
			_harmony = new Harmony("moxy.deepwater");
			SwimItems.Bind(((BaseUnityPlugin)this).Config, _harmony);
			Breath.Bind(((BaseUnityPlugin)this).Config, _harmony);
			UnderwaterAudio.Patch(_harmony);
			UnderwaterSfx.Patch(_harmony);
			Underwater._flipY = ((BaseUnityPlugin)this).Config.Bind<bool>("Look", "UndersideFlipY", false, "Flip the world-above picture seen through the water surface (if it's upside down on your system).");
			((Component)this).gameObject.AddComponent<Underwater>();
			((Component)this).gameObject.AddComponent<Breath>();
			Log.LogInfo((object)"DeepWater 0.15.3 loaded.");
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextSeaDepth))
			{
				_nextSeaDepth = Time.unscaledTime + 0.5f;
				ApplySeaDepth();
			}
		}

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

		private void ApplySeaDepth()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			float value = _seaDepth.Value;
			if (value < 0f)
			{
				return;
			}
			foreach (WaterVolume instance in WaterVolume.Instances)
			{
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_waterSurface == (Object)null || instance.m_forceDepth >= 0f)
				{
					continue;
				}
				float[] array = _wvDepth.Invoke(instance);
				if (array == null || array.Length < 4)
				{
					continue;
				}
				bool flag = false;
				for (int i = 0; i < 4; i++)
				{
					if (array[i] < value)
					{
						flag = true;
					}
				}
				if (flag && _seaDepthLogged.Add(((Object)instance).GetInstanceID()) && _seaDepthLogged.Count < 40)
				{
					Vector2s zone = ZoneSystem.GetZone(((Component)instance).transform.position);
					Log.LogInfo((object)$"Water tile {zone.x},{zone.y}: corner depths {array[0]:0.00}/{array[1]:0.00}/{array[2]:0.00}/{array[3]:0.00} raised to {value:0.00}");
				}
				for (int j = 0; j < 4; j++)
				{
					if (array[j] < value)
					{
						array[j] = value;
					}
					_seaDepthArr[j] = array[j];
				}
				_wvOneDepth.Invoke(instance) = ((array[0] == array[1] && array[1] == array[2] && array[2] == array[3]) ? array[0] : (-1f));
				Material sharedMaterial = ((Renderer)instance.m_waterSurface).sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null && ((Object)sharedMaterial).name.EndsWith("(Instance)"))
				{
					sharedMaterial.SetFloatArray("_depth", _seaDepthArr);
				}
			}
		}
	}
	internal static class ShaderBundle
	{
		private static AssetBundle _bundle;

		private static bool _tried;

		public static Shader Get(string name)
		{
			if (!_tried)
			{
				_tried = true;
				string text = Path.Combine(Path.GetDirectoryName(typeof(ShaderBundle).Assembly.Location) ?? ".", "deepwater_shaders");
				if (File.Exists(text))
				{
					_bundle = AssetBundle.LoadFromFile(text);
				}
				Plugin.Log.LogInfo((object)(((Object)(object)_bundle != (Object)null) ? ("Shader bundle loaded: " + string.Join(", ", _bundle.GetAllAssetNames())) : ("Shader bundle not found at " + text)));
			}
			if ((Object)(object)_bundle == (Object)null)
			{
				return null;
			}
			Shader[] array = _bundle.LoadAllAssets<Shader>();
			foreach (Shader val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == name)
				{
					if (!val.isSupported)
					{
						return null;
					}
					return val;
				}
			}
			return null;
		}
	}
	internal static class SwimItems
	{
		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<bool> _dive;

		private static ConfigEntry<float> _diveSpeed;

		private static ConfigEntry<bool> _cameraUnder;

		private static ConfigEntry<bool> _rideWaves;

		private static FieldRef<Character, Rigidbody> _body;

		private static FieldRef<Character, GameObject> _visual = AccessTools.FieldRefAccess<Character, GameObject>("m_visual");

		internal static bool Underwater;

		private static FieldRef<Character, ZSyncAnimation> _zanim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim");

		private static readonly int s_inWaterHash = ZSyncAnimation.GetHash("inWater");

		private static float _vy;

		private static ConfigEntry<float> _floatRegen;

		private static ConfigEntry<float> _wadeSlow;

		private static readonly FieldRef<Character, CapsuleCollider> _capsule = AccessTools.FieldRefAccess<Character, CapsuleCollider>("m_collider");

		private static readonly FieldRef<Player, float> _stamina = AccessTools.FieldRefAccess<Player, float>("m_stamina");

		private static readonly FieldRef<Player, float> _regenTimer = AccessTools.FieldRefAccess<Player, float>("m_staminaRegenTimer");

		private static bool _vyActive;

		internal static float Pitch;

		public static void Bind(ConfigFile cfg, Harmony harmony)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Expected O, but got Unknown
			_enabled = cfg.Bind<bool>("Gameplay", "UseItemsWhileSwimming", true, "Keep tools and weapons usable while swimming (build, dig, hoe, attack). Your own player only.");
			HarmonyMethod val = new HarmonyMethod(typeof(SwimItems), "Transpiler", (Type[])null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "UpdateEquipment", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
			_dive = cfg.Bind<bool>("Gameplay", "DiveWithCrouch", true, "While swimming, hold Crouch to dive (Jump swims up faster); the camera may follow you under water.");
			_diveSpeed = cfg.Bind<float>("Gameplay", "DiveSpeed", 3f, new ConfigDescription("Diving speed (m/s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			_rideWaves = cfg.Bind<bool>("Gameplay", "RideWaves", true, "Floating at the surface you stay on top of the waves (vanilla lets big waves wash over you). Dive with Crouch to go under.");
			_cameraUnder = cfg.Bind<bool>("Gameplay", "CameraUnderWater", true, "The camera may go below the water surface (vanilla keeps it above).");
			_body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");
			_floatRegen = cfg.Bind<float>("Gameplay", "FloatingStaminaRegen", 0.2f, new ConfigDescription("Stamina regenerates at this fraction of the normal rate while you hold still in the water (vanilla: none while swimming). 0 = off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "UpdateStats", new Type[1] { typeof(float) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "StatsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_wadeSlow = cfg.Bind<float>("Gameplay", "SubmergedWalkSpeed", 0.4f, new ConfigDescription("Creatures walking on the bottom fully under water move at this fraction of their land speed (knee deep already ~70%; vanilla barely slows slow walkers). 1 = vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "ApplyLiquidResistance", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "LiquidResistancePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "UpdateSwimming", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "SwimPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(GameCamera), "GetCameraPosition", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SwimItems), "CameraTranspiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void LiquidResistancePostfix(Character __instance, ref float speed)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!(_wadeSlow.Value >= 0.999f) && !((Object)(object)__instance == (Object)null) && !__instance.IsPlayer())
			{
				float num = __instance.GetLiquidLevel() - ((Component)__instance).transform.position.y;
				if (!(num <= 0f))
				{
					CapsuleCollider val = _capsule.Invoke(__instance);
					float num2 = (((Object)(object)val != (Object)null) ? Mathf.Max(0.5f, val.height * ((Component)__instance).transform.lossyScale.y) : 2f);
					float num3 = Mathf.Clamp01(num / num2);
					speed *= Mathf.Lerp(1f, _wadeSlow.Value, Mathf.Sqrt(num3));
				}
			}
		}

		private static void StatsPostfix(Player __instance, float dt)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			if (_floatRegen.Value <= 0f || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).IsSwimming() || ((Character)__instance).IsOnGround() || ((Character)__instance).IsDead())
			{
				return;
			}
			Vector3 val = ((Character)__instance).GetMoveDir();
			if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
			{
				return;
			}
			val = ((Character)__instance).GetVelocity();
			if (!(((Vector3)(ref val)).sqrMagnitude > 1f) && !ZInput.GetButton("Jump") && !ZInput.GetButton("JoyJump") && !ZInput.GetButton("Crouch") && !ZInput.GetButton("JoyCrouch") && !(_regenTimer.Invoke(__instance) > 0f))
			{
				float maxStamina = ((Character)__instance).GetMaxStamina();
				ref float reference = ref _stamina.Invoke(__instance);
				if (!(reference >= maxStamina))
				{
					float num = (__instance.m_staminaRegen + (1f - reference / maxStamina) * __instance.m_staminaRegen * __instance.m_staminaRegenTimeMultiplier) * _floatRegen.Value;
					reference = Mathf.Min(maxStamina, reference + num * dt * Game.m_staminaRegenRate);
				}
			}
		}

		private static void SwimPostfix(Character __instance, float dt)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			if (!_dive.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)__instance;
			Rigidbody val2 = _body.Invoke(__instance);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			bool flag = ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch");
			bool flag2 = ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump");
			float liquidLevel = __instance.GetLiquidLevel();
			bool flag3 = ((Component)__instance).transform.position.y < liquidLevel - __instance.m_swimDepth - 0.3f;
			if (!flag && (!Underwater || !flag3))
			{
				Underwater = false;
				_vyActive = false;
				if (_rideWaves.Value && !__instance.IsOnGround())
				{
					RideWaves(__instance, val2, liquidLevel, dt);
				}
				return;
			}
			Vector3 lookDir = ((Character)val).GetLookDir();
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(lookDir.x, 0f, lookDir.z);
			val3 = ((((Vector3)(ref val3)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val3)).normalized : ((Component)val).transform.forward);
			float num = Mathf.Clamp(Vector3.Dot(__instance.GetMoveDir(), val3), -1f, 1f);
			float num2 = __instance.m_swimSpeed * 1.2f;
			float num3 = lookDir.y * num * num2;
			if (flag)
			{
				num3 -= _diveSpeed.Value;
			}
			if (flag2)
			{
				num3 += _diveSpeed.Value * 0.7f;
			}
			Vector3 linearVelocity = val2.linearVelocity;
			if (!_vyActive)
			{
				_vy = Mathf.Min(linearVelocity.y, 0f);
				_vyActive = true;
			}
			_vy = Mathf.MoveTowards(_vy, num3, 15f * dt);
			linearVelocity.y = _vy;
			val2.linearVelocity = linearVelocity;
			val2.useGravity = false;
			Underwater = true;
			ZSyncAnimation val4 = _zanim.Invoke(__instance);
			if ((Object)(object)val4 != (Object)null)
			{
				val4.SetBool(s_inWaterHash, true);
			}
			float num4 = ((num > 0.1f) ? ((0f - Mathf.Asin(Mathf.Clamp(lookDir.y, -1f, 1f))) * 57.29578f * num) : 0f);
			if (flag && num <= 0.1f)
			{
				num4 = 45f;
			}
			if (flag2 && num <= 0.1f)
			{
				num4 = -45f;
			}
			Pitch = Mathf.MoveTowards(Pitch, num4, 180f * dt);
		}

		private static void RideWaves(Character c, Rigidbody body, float level, float dt)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			float num = level - c.m_swimDepth;
			Vector3 linearVelocity = body.linearVelocity;
			float num2 = Mathf.Clamp((num - ((Component)c).transform.position.y) * 8f, -8f, 8f);
			linearVelocity.y = Mathf.MoveTowards(linearVelocity.y, num2, 80f * dt);
			body.linearVelocity = linearVelocity;
			body.useGravity = false;
		}

		internal static void ApplyTilt(Player p)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)p != (Object)null) ? _visual.Invoke((Character)(object)p) : null);
			if (!((Object)(object)val == (Object)null))
			{
				if (!Underwater)
				{
					Pitch = Mathf.MoveTowards(Pitch, 0f, 180f * Time.deltaTime);
				}
				Quaternion val2 = Quaternion.Euler(Pitch, 0f, 0f);
				Vector3 val3 = Vector3.up * 1f;
				val.transform.localRotation = val2;
				val.transform.localPosition = val3 - val2 * val3;
			}
		}

		private static IEnumerable<CodeInstruction> CameraTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo orig = AccessTools.Method(typeof(Floating), "GetLiquidLevel", new Type[3]
			{
				typeof(Vector3),
				typeof(float),
				typeof(LiquidType)
			}, (Type[])null);
			MethodInfo ours = AccessTools.Method(typeof(SwimItems), "CameraLiquidLevel", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, orig))
				{
					yield return CodeInstructionExtensions.WithBlocks(CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)ours), (IEnumerable<Label>)instruction.labels), (IEnumerable<ExceptionBlock>)instruction.blocks);
				}
				else
				{
					yield return instruction;
				}
			}
		}

		private static float CameraLiquidLevel(Vector3 p, float waveFactor, LiquidType type)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (_cameraUnder.Value)
			{
				return -10000f;
			}
			return Floating.GetLiquidLevel(p, waveFactor, type);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo isSwimming = AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null);
			MethodInfo ours = AccessTools.Method(typeof(SwimItems), "IsSwimmingForItems", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, isSwimming))
				{
					yield return CodeInstructionExtensions.WithBlocks(CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)ours), (IEnumerable<Label>)instruction.labels), (IEnumerable<ExceptionBlock>)instruction.blocks);
				}
				else
				{
					yield return instruction;
				}
			}
		}

		private static bool IsSwimmingForItems(Character c)
		{
			if (_enabled != null && _enabled.Value && (Object)(object)c != (Object)null && (Object)(object)c == (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if ((Object)(object)c != (Object)null)
			{
				return c.IsSwimming();
			}
			return false;
		}
	}
	[DefaultExecutionOrder(32000)]
	internal sealed class Underwater : MonoBehaviour
	{
		private static readonly Color TarColor = new Color(0.016f, 0.01f, 0.006f, 1f);

		private bool _tarLook;

		internal static ConfigEntry<bool> _flipY;

		private static readonly int SunFogColorId = Shader.PropertyToID("_SunFogColor");

		private static readonly int SunColorId = Shader.PropertyToID("_SunColor");

		private static readonly int AmbientColorId = Shader.PropertyToID("_AmbientColor");

		private Color _waterColor = new Color(0.02f, 0.1f, 0.15f);

		private float _fogDensity = 0.1f;

		private static readonly Color ShallowColor = new Color(0.06f, 0.25f, 0.29f, 1f);

		private static readonly Color MidColor = new Color(0.02f, 0.1f, 0.15f, 1f);

		private static readonly Color DeepColor = new Color(0.003f, 0.015f, 0.03f, 1f);

		private const float FullDarkDepth = 40f;

		private float _blend;

		private bool _saved;

		private bool _savedFog;

		private FogMode _savedMode;

		private float _sunWritten = -1f;

		private float _sunBase;

		private ParticleSystem _motes;

		private Vector3 _current;

		private bool _motesBlended;

		internal static Vector3 Current;

		private readonly Caustics _caustics = new Caustics();

		private readonly Bubbles _bubbles = new Bubbles();

		private readonly UnderwaterAudio _audio = new UnderwaterAudio();

		private static readonly int s_wet = Shader.PropertyToID("_Wet");

		private Shader _additive;

		private bool _shaderSearched;

		private float _shaderRetryAt;

		private readonly Stopwatch _sw = new Stopwatch();

		private double _tBubbles;

		private double _tMotes;

		private double _tCaustics;

		private double _tSheet;

		private double _tAbove;

		private int _tFrames;

		private int _tRenders;

		private float _tStart = -1f;

		private Material _splitMat;

		private bool _splitSearched;

		private Camera _scam;

		private RenderTexture _srt;

		private CommandBuffer _splitCb;

		private Camera _cbCam;

		private bool _splitOn;

		private bool _splitTar;

		private Color _cleanFogColor;

		private Color _cleanAmbient = Color.gray;

		private Color _cleanSunFog;

		private Color _cleanSunCol;

		private Color _cleanAmbCol;

		private float _cleanFogDensity = 0.01f;

		private Color _wFogColor;

		private Color _wAmbient;

		private Color _wSunFog;

		private Color _wSunCol;

		private Color _wAmbCol;

		private float _wFogDensity = -1f;

		private AmplifyOcclusionEffect _sao;

		private float _nextAoSync;

		private static FieldInfo[] _aoFields;

		private Material _fogMat;

		private bool _fogSearched;

		private CommandBuffer _fogCb;

		private Material _ppFogMat;

		private int _fogPass = -1;

		internal static float Daylight = 1f;

		private float _nextDaylightLog;

		private Color _savedAmbient;

		private bool _savedAmbientValid;

		private PostProcessingProfile _profile;

		private bool _postSaved;

		private bool _bloomOn;

		private bool _vignetteOn;

		private Settings _bloom;

		private Settings _vignette;

		private Behaviour _shafts;

		private AmplifyOcclusionEffect _ao;

		private ApplicationMethod _aoMethod;

		private const int GridN = 37;

		private const float GridStep = 4f;

		private const float SkirtRadius = 3000f;

		private int[] _edge;

		private GameObject _sheet;

		private MeshRenderer _sheetRenderer;

		private Mesh _sheetMesh;

		private Material _sheetMat;

		private Vector3[] _sv;

		private Vector3[] _sn;

		private WaterVolume _sheetWv;

		private float _gridLevel = float.NaN;

		private float _ox = float.NaN;

		private float _oz = float.NaN;

		private static readonly FieldRef<float> _wTime = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(typeof(WaterVolume), "s_wrappedDayTimeSeconds"));

		private static readonly FieldRef<Vector4> _wWind1 = AccessTools.StaticFieldRefAccess<Vector4>(AccessTools.Field(typeof(WaterVolume), "s_globalWind1"));

		private static readonly FieldRef<Vector4> _wWind2 = AccessTools.StaticFieldRefAccess<Vector4>(AccessTools.Field(typeof(WaterVolume), "s_globalWind2"));

		private static readonly FieldRef<float> _wAlpha = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(typeof(WaterVolume), "s_globalWindAlpha"));

		private readonly Collider[] _wvBuf = (Collider[])(object)new Collider[8];

		private int _wvMask;

		private Camera _rcam;

		private int _aboveFrame;

		private int _aboveMask;

		private readonly Plane[] _planes = (Plane[])(object)new Plane[6];

		private double _aboveMs;

		internal static int _aboveRendered;

		internal static int _aboveSkipped;

		private RenderTexture _rt;

		private bool _noShader;

		private bool _normalSearched;

		private bool _farLogged;

		private Particle[] _moteBuf;

		public static bool CameraUnder { get; private set; }

		public static bool CameraInTar { get; private set; }

		public static bool VisualUnder { get; private set; }

		private double Lap()
		{
			double totalMilliseconds = _sw.Elapsed.TotalMilliseconds;
			_sw.Restart();
			return totalMilliseconds;
		}

		private void ReportCost(bool under)
		{
			if (!under)
			{
				_tStart = -1f;
				return;
			}
			_tFrames++;
			if (_tStart < 0f)
			{
				_tStart = Time.unscaledTime;
				_tFrames = 0;
				_tBubbles = (_tMotes = (_tCaustics = (_tSheet = (_tAbove = 0.0))));
				_tRenders = _aboveRendered;
				return;
			}
			float num = Time.unscaledTime - _tStart;
			if (!(num < 5f) && _tFrames != 0)
			{
				double num2 = _tFrames;
				Plugin.Log.LogInfo((object)($"Underwater cost per frame (CPU, {num2 / (double)num:0} fps): above-water camera {_tAbove / num2:0.00} ms " + $"({_aboveRendered - _tRenders} renders in {_tFrames} frames), water sheet {(_tSheet - _tAbove) / num2:0.00} ms, " + $"caustics {_tCaustics / num2:0.00} ms, motes {_tMotes / num2:0.00} ms, bubbles {_tBubbles / num2:0.00} ms"));
				_tStart = -1f;
			}
		}

		private void LateUpdate()
		{
			//IL_0028: 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_00a9: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Unknown result type (might be due to invalid IL or missing references)
			//IL_0584: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_051c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0592: Unknown result type (might be due to invalid IL or missing references)
			//IL_0597: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0646: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0653: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_067f: Unknown result type (might be due to invalid IL or missing references)
			//IL_068a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0699: Unknown result type (might be due to invalid IL or missing references)
			//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				SwimItems.ApplyTilt(localPlayer);
				_caustics.Prewarm();
			}
			CaptureClean();
			_savedAmbient = _cleanAmbient;
			_savedAmbientValid = true;
			DaylightFactor();
			_sw.Restart();
			_bubbles.Update(AdditiveShader());
			double num = Lap();
			Camera mainCamera = Utils.GetMainCamera();
			CameraUnder = false;
			if ((Object)(object)mainCamera == (Object)null)
			{
				SetMotes(null, on: false, 0f, 0f);
				SetSurface(null, on: false, 0f, 0f);
				RestorePost();
				return;
			}
			Vector3 position = ((Component)mainCamera).transform.position;
			float liquidLevel = Floating.GetLiquidLevel(position, 1f, (LiquidType)0);
			float num2 = NearHalfHeight(mainCamera);
			CameraUnder = liquidLevel > -9999f && position.y < liquidLevel - num2 - 0.05f;
			float num3 = ((liquidLevel > -9999f) ? (-10000f) : Floating.GetLiquidLevel(position, 1f, (LiquidType)1));
			CameraInTar = num3 > -9999f && position.y < num3 - num2 - 0.02f;
			bool flag = SplitWanted(position, liquidLevel, num2);
			bool flag2 = !flag && !CameraInTar && num3 > -9999f && position.y < num3 + num2 + 0.05f;
			_splitOn = (flag || flag2) && EnsureSplitMaterial();
			_splitTar = _splitOn && flag2;
			if (_splitOn)
			{
				RenderSplitAbove(mainCamera);
			}
			SetSplitComposite(mainCamera, _splitOn);
			VisualUnder = CameraUnder || (_splitOn && !_splitTar);
			if (CameraInTar || _splitTar)
			{
				_tarLook = true;
			}
			else if (VisualUnder)
			{
				_tarLook = false;
			}
			float num4 = (VisualUnder ? Mathf.Clamp01((liquidLevel - position.y) / 40f) : 0f);
			_blend = (_splitOn ? 1f : Mathf.MoveTowards(_blend, (CameraUnder || CameraInTar) ? 1f : 0f, Time.deltaTime * 6f));
			_audio.Update(CameraUnder ? _blend : 0f, num4);
			UnderwaterSfx.Update(CameraUnder);
			if (CameraUnder && _blend > 0f && Shader.GetGlobalFloat(s_wet) < _blend)
			{
				Shader.SetGlobalFloat(s_wet, _blend);
			}
			Lap();
			SetMotes(mainCamera, VisualUnder, num4, liquidLevel);
			double num5 = Lap();
			_caustics.Update(mainCamera, VisualUnder, liquidLevel, num4, VisualUnder ? AdditiveShader() : null);
			double num6 = Lap();
			_aboveMs = 0.0;
			SetSurface(mainCamera, VisualUnder, liquidLevel, num4);
			double num7 = Lap();
			if (CameraUnder)
			{
				_tBubbles += num;
				_tMotes += num5;
				_tCaustics += num6;
				_tSheet += num7;
				_tAbove += _aboveMs;
			}
			ReportCost(CameraUnder);
			if (_blend <= 0f)
			{
				if (_saved)
				{
					RenderSettings.fog = _savedFog;
					RenderSettings.fogMode = _savedMode;
					_saved = false;
					RenderSettings.fogColor = _cleanFogColor;
					RenderSettings.fogDensity = _cleanFogDensity;
					RenderSettings.ambientLight = _cleanAmbient;
					Shader.SetGlobalColor(SunFogColorId, _cleanSunFog);
					Shader.SetGlobalColor(SunColorId, _cleanSunCol);
					Shader.SetGlobalColor(AmbientColorId, _cleanAmbCol);
				}
				RestoreSun();
				RestorePost();
				return;
			}
			if (!_saved)
			{
				_savedFog = RenderSettings.fog;
				_savedMode = RenderSettings.fogMode;
				_saved = true;
			}
			if (_tarLook && !VisualUnder)
			{
				Color val = TarColor * Mathf.Max(0.3f, Daylight);
				RenderSettings.fog = true;
				RenderSettings.fogMode = (FogMode)2;
				RenderSettings.fogColor = Color.Lerp(RenderSettings.fogColor, val, _blend);
				RenderSettings.fogDensity = Mathf.Lerp(RenderSettings.fogDensity, 2.2f, _blend);
				RenderSettings.ambientLight = Color.Lerp(Render