Decompiled source of DryPits v1.0.0

plugins/DryPits.dll

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

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DryPits
{
	internal static class DryPitsSystem
	{
		private sealed class Binding
		{
			internal readonly int Zx;

			internal readonly int Zz;

			internal readonly Heightmap Heightmap;

			internal readonly WaterSurfaceView View;

			internal readonly float LoadedAt;

			internal WaterRecord Record;

			internal ZNetView Terrain;

			internal int ShownRevision = -1;

			internal float NextVisual;

			internal float NextTerrainLookup;

			internal float NextRecordCheck;

			internal bool WasCustom;

			internal bool StateLoaded;

			internal Binding(int zx, int zz, Heightmap heightmap, WaterSurfaceView view, float now)
			{
				Zx = zx;
				Zz = zz;
				Heightmap = heightmap;
				View = view;
				LoadedAt = now;
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__36_0;

			internal void <RegisterCommand>b__36_0(ConsoleEventArgs args)
			{
				foreach (string item in Describe())
				{
					Terminal context = args.Context;
					if (context != null)
					{
						context.AddString(item);
					}
					Plugin.Log(item);
				}
			}
		}

		private const string PlanetWorldKey = "planetprototype_v1";

		internal static readonly FloodGrid Grid = new FloodGrid();

		internal static bool QueryActive;

		private static readonly Dictionary<long, Binding> bindings = new Dictionary<long, Binding>();

		private static readonly Dictionary<Heightmap, long> zoneOf = new Dictionary<Heightmap, long>();

		private static readonly Dictionary<Heightmap, float[]> baseHeights = new Dictionary<Heightmap, float[]>();

		private static readonly Dictionary<long, WaterRecord> records = new Dictionary<long, WaterRecord>();

		private static readonly Dictionary<ZNetView, WaterRecord> recordViews = new Dictionary<ZNetView, WaterRecord>();

		private static readonly List<WaterRecord> duplicates = new List<WaterRecord>();

		private static readonly List<ZDO> sectorObjects = new List<ZDO>();

		private static readonly FieldRef<Heightmap, List<float>> heightsOf = AccessTools.FieldRefAccess<Heightmap, List<float>>("m_heights");

		private static readonly float[] groundBuffer = new float[4225];

		private static readonly float[] originalBuffer = new float[4225];

		private static World checkedWorld;

		private static bool worldAllowed;

		private static bool suspended;

		private static bool announced;

		private static float nextFlush;

		private static bool WorldAllowed()
		{
			if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || WorldGenerator.instance == null)
			{
				return false;
			}
			World world = WorldGenerator.instance.m_world;
			if (world != checkedWorld)
			{
				checkedWorld = world;
				worldAllowed = world != null && !world.m_menu && !world.m_startingGlobalKeys.Contains("planetprototype_v1");
				if (world != null && !world.m_menu && !worldAllowed)
				{
					Plugin.Log("PlanetPrototype world: Dry Pits stays inactive here.");
				}
			}
			return worldAllowed;
		}

		internal static void ResetSession()
		{
			foreach (Binding value in bindings.Values)
			{
				value.View.Dispose();
			}
			bindings.Clear();
			zoneOf.Clear();
			baseHeights.Clear();
			records.Clear();
			recordViews.Clear();
			duplicates.Clear();
			Grid.Clear();
			DungeonVolumes.Clear();
			DungeonVolumes.Active = false;
			QueryActive = false;
			checkedWorld = null;
			announced = false;
			nextFlush = 0f;
		}

		internal static void DungeonsChanged()
		{
			foreach (FloodPage item in new List<FloodPage>(Grid.Pages))
			{
				Grid.SetDungeon(item.Zx, item.Zz, DungeonVolumes.WaterZones.Contains(FloodGrid.Key(item.Zx, item.Zz)));
			}
		}

		internal static void CaptureBase(Heightmap hm, float[] heights)
		{
			if ((Object)(object)hm != (Object)null && heights != null)
			{
				baseHeights[hm] = heights;
			}
		}

		internal static void HeightsChanged(Heightmap hm)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0080: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			if (hm.IsDistantLod || hm.m_width != 64 || Mathf.Abs(hm.m_scale - 1f) > 0.001f || !WorldAllowed())
			{
				return;
			}
			List<float> list = heightsOf.Invoke(hm);
			if (list == null || list.Count != 4225)
			{
				return;
			}
			Vector3 position = ((Component)hm).transform.position;
			int num = Mathf.RoundToInt(position.x / 64f);
			int num2 = Mathf.RoundToInt(position.z / 64f);
			if (Mathf.Abs(position.x - (float)num * 64f) > 0.01f || Mathf.Abs(position.z - (float)num2 * 64f) > 0.01f)
			{
				return;
			}
			long num3 = FloodGrid.Key(num, num2);
			float time = Time.time;
			if (!bindings.TryGetValue(num3, out var value) || value.Heightmap != hm)
			{
				WaterSurfaceView waterSurfaceView = WaterSurfaceView.Find(hm);
				if (waterSurfaceView == null)
				{
					return;
				}
				if (value != null)
				{
					Release(num3, value);
				}
				value = (bindings[num3] = new Binding(num, num2, hm, waterSurfaceView, time));
				zoneOf[hm] = num3;
				if (records.TryGetValue(num3, out var value2))
				{
					value.Record = value2;
				}
			}
			float num4 = position.y - ZoneSystem.instance.m_waterLevel;
			baseHeights.TryGetValue(hm, out var value3);
			bool flag = value3 != null && value3.Length == 4225;
			for (int i = 0; i < 4225; i++)
			{
				groundBuffer[i] = list[i] + num4;
				originalBuffer[i] = (flag ? value3[i] : list[i]) + num4;
			}
			bool num5 = Grid.Page(num, num2) == null;
			if ((Object)(object)value.Record == (Object)null)
			{
				value.NextTerrainLookup = 0f;
			}
			Grid.UpdateGround(num, num2, groundBuffer, originalBuffer, IsAuthority(value, time), flag);
			Grid.SetDungeon(num, num2, DungeonVolumes.WaterZones.Contains(num3));
			if (num5 && (Object)(object)value.Record != (Object)null)
			{
				value.StateLoaded = true;
			}
		}

		internal static void HeightmapDestroyed(Heightmap hm)
		{
			baseHeights.Remove(hm);
			if (zoneOf.TryGetValue(hm, out var value))
			{
				if (bindings.TryGetValue(value, out var value2) && value2.Heightmap == hm)
				{
					Flush(value2);
					Release(value, value2);
				}
				zoneOf.Remove(hm);
			}
		}

		private static void Release(long key, Binding binding)
		{
			binding.View.Dispose();
			bindings.Remove(key);
			zoneOf.Remove(binding.Heightmap);
			Grid.Remove(binding.Zx, binding.Zz);
		}

		private static bool IsAuthority(Binding b, float now)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			WaterRecord record = b.Record;
			if ((Object)(object)record != (Object)null && record.Valid)
			{
				return record.View.IsOwner();
			}
			if (now >= b.NextTerrainLookup)
			{
				b.NextTerrainLookup = now + 1f;
				TerrainComp val = TerrainComp.FindTerrainCompiler(new Vector3((float)b.Zx * 64f, 0f, (float)b.Zz * 64f));
				b.Terrain = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ZNetView>() : null);
			}
			if ((Object)(object)b.Terrain != (Object)null && b.Terrain.IsValid())
			{
				return b.Terrain.IsOwner();
			}
			return false;
		}

		internal static void Tick()
		{
			DungeonVolumes.Active = Plugin.Enabled.Value && WorldAllowed();
			if (!DungeonVolumes.Active)
			{
				if (suspended)
				{
					return;
				}
				suspended = true;
				QueryActive = false;
				{
					foreach (Binding value2 in bindings.Values)
					{
						value2.View.Restore();
					}
					return;
				}
			}
			if (suspended)
			{
				suspended = false;
				foreach (Binding value3 in bindings.Values)
				{
					value3.ShownRevision = -1;
				}
			}
			float time = Time.time;
			RemoveDuplicates();
			foreach (Binding value4 in bindings.Values)
			{
				FloodPage floodPage = Grid.Page(value4.Zx, value4.Zz);
				if (floodPage != null)
				{
					Grid.SetAuthority(floodPage, IsAuthority(value4, time));
				}
			}
			float value = Plugin.FillSpeed.Value;
			if (value > 0f && value <= 10f)
			{
				Grid.Step(Mathf.Min(Time.deltaTime, 0.1f) * value);
			}
			bool flag = false;
			foreach (Binding value5 in bindings.Values)
			{
				FloodPage floodPage2 = Grid.Page(value5.Zx, value5.Zz);
				if (floodPage2 == null)
				{
					continue;
				}
				flag |= floodPage2.Custom;
				if (floodPage2.Revision != value5.ShownRevision && time >= value5.NextVisual)
				{
					value5.ShownRevision = floodPage2.Revision;
					value5.NextVisual = time + 0.2f;
					if (floodPage2.Custom)
					{
						value5.View.Show(floodPage2, time);
					}
					else
					{
						value5.View.Restore();
					}
					if (floodPage2.Custom != value5.WasCustom)
					{
						value5.WasCustom = floodPage2.Custom;
						string text = "zone " + value5.Zx + "," + value5.Zz + (floodPage2.Custom ? (" uses local water (" + value5.View.TriangleCount + " water triangles)") : " is back to vanilla water");
						if (floodPage2.Custom && !announced)
						{
							announced = true;
							Plugin.Log("First dry pit this session: " + text);
						}
						else
						{
							Plugin.Trace(text);
						}
					}
				}
				value5.View.Update(time);
				CreateRecordIfNeeded(value5, floodPage2, time);
			}
			QueryActive = flag;
			if (time >= nextFlush)
			{
				nextFlush = time + 1f;
				FlushAll();
			}
		}

		private static void CreateRecordIfNeeded(Binding b, FloodPage page, float now)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			if ((Object)(object)b.Record != (Object)null || !page.Authority || !page.PersistDirty || now < b.NextRecordCheck || now - b.LoadedAt < 5f)
			{
				return;
			}
			b.NextRecordCheck = now + 2f;
			if (ZoneState.Capture(page).Trivial)
			{
				page.PersistDirty = false;
				return;
			}
			Vector2s val = default(Vector2s);
			((Vector2s)(ref val))..ctor(b.Zx, b.Zz);
			if ((Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || !ZoneSystem.instance.IsZoneLoaded(val))
			{
				return;
			}
			sectorObjects.Clear();
			ZDOMan.instance.FindSectorObjects(val, new SimulationDistance(0, 0, false), sectorObjects, (List<ZDO>)null);
			foreach (ZDO sectorObject in sectorObjects)
			{
				if (sectorObject.GetPrefab() == WaterRecord.PrefabHash)
				{
					return;
				}
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(WaterRecord.PrefabHash);
			if (!((Object)(object)prefab == (Object)null))
			{
				Object.Instantiate<GameObject>(prefab, new Vector3((float)b.Zx * 64f, ZoneSystem.instance.m_waterLevel, (float)b.Zz * 64f), Quaternion.identity);
				Plugin.Trace("zone " + b.Zx + "," + b.Zz + ": water record created");
			}
		}

		internal static void RegisterRecord(WaterRecord record)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			long key = FloodGrid.Key(record.Zx, record.Zz);
			if (records.TryGetValue(key, out var value) && (Object)(object)value != (Object)(object)record && (Object)(object)value != (Object)null && value.Valid)
			{
				ZDOID uid = value.Uid;
				bool num = ((ZDOID)(ref uid)).CompareTo(record.Uid) <= 0;
				WaterRecord waterRecord = (num ? record : value);
				if (waterRecord.Owned)
				{
					duplicates.Add(waterRecord);
				}
				if (num)
				{
					record.Rejected = true;
					return;
				}
				UnregisterRecord(value);
				value.Rejected = true;
			}
			records[key] = record;
			recordViews[record.View] = record;
			record.Registered = true;
			if (bindings.TryGetValue(key, out var value2))
			{
				value2.Record = record;
				value2.NextTerrainLookup = 0f;
			}
			RecordChanged(record);
		}

		internal static void UnregisterRecord(WaterRecord record)
		{
			if (record.Registered)
			{
				record.Registered = false;
				long key = FloodGrid.Key(record.Zx, record.Zz);
				if (records.TryGetValue(key, out var value) && (Object)(object)value == (Object)(object)record)
				{
					records.Remove(key);
				}
				if (record.View != null)
				{
					recordViews.Remove(record.View);
				}
				if (bindings.TryGetValue(key, out var value2) && (Object)(object)value2.Record == (Object)(object)record)
				{
					value2.Record = null;
				}
			}
		}

		internal static void RecordChanged(WaterRecord record)
		{
			if (!record.Registered)
			{
				return;
			}
			byte[] array = record.Read();
			if (array == null || array.Length == 0)
			{
				return;
			}
			ZoneState zoneState = null;
			try
			{
				zoneState = ZoneState.Deserialize(Utils.Decompress(array));
			}
			catch (Exception)
			{
			}
			if (zoneState == null)
			{
				Plugin.Log("zone " + record.Zx + "," + record.Zz + ": ignored a damaged water record");
				return;
			}
			bindings.TryGetValue(FloodGrid.Key(record.Zx, record.Zz), out var value);
			FloodPage floodPage = Grid.Page(record.Zx, record.Zz);
			if (value == null || floodPage == null || !floodPage.Authority || !value.StateLoaded)
			{
				Grid.ApplyRecord(record.Zx, record.Zz, zoneState);
				if (value != null && floodPage != null)
				{
					value.StateLoaded = true;
				}
			}
		}

		private static void RemoveDuplicates()
		{
			if (duplicates.Count == 0 || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			foreach (WaterRecord duplicate in duplicates)
			{
				if ((Object)(object)duplicate != (Object)null && duplicate.Owned)
				{
					ZNetScene.instance.Destroy(((Component)duplicate).gameObject);
				}
			}
			duplicates.Clear();
		}

		private static void Flush(Binding b)
		{
			FloodPage floodPage = Grid.Page(b.Zx, b.Zz);
			if (floodPage != null && floodPage.Loaded && floodPage.Authority && floodPage.PersistDirty && !((Object)(object)b.Record == (Object)null) && b.Record.Owned)
			{
				b.Record.Write(Utils.Compress(ZoneState.Capture(floodPage).Serialize()));
				floodPage.PersistDirty = false;
				b.StateLoaded = true;
			}
		}

		internal static void FlushAll()
		{
			foreach (Binding value in bindings.Values)
			{
				Flush(value);
			}
		}

		internal static void BeforeViewReset(ZNetView view)
		{
			if (recordViews.Count != 0 && recordViews.TryGetValue(view, out var value))
			{
				if (bindings.TryGetValue(FloodGrid.Key(value.Zx, value.Zz), out var value2) && (Object)(object)value2.Record == (Object)(object)value)
				{
					Flush(value2);
				}
				UnregisterRecord(value);
			}
		}

		internal static void RegisterCommand()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__36_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					foreach (string item in Describe())
					{
						Terminal context = args.Context;
						if (context != null)
						{
							context.AddString(item);
						}
						Plugin.Log(item);
					}
				};
				<>c.<>9__36_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("drypits", "Dry Pits: water state at the player (also written to the BepInEx log)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static List<string> Describe()
		{
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: 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_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cf: 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)
			List<string> list = new List<string>();
			int num = 0;
			foreach (Binding value2 in bindings.Values)
			{
				FloodPage floodPage = Grid.Page(value2.Zx, value2.Zz);
				if (floodPage != null && floodPage.Custom)
				{
					num++;
				}
			}
			list.Add("Dry Pits 0.3.0: enabled=" + Plugin.Enabled.Value + ", world ok=" + WorldAllowed() + ", zones=" + bindings.Count + ", zones with local water=" + num + ", records=" + records.Count + ", fill speed=" + Plugin.FillSpeed.Value + ", simulated samples=" + Grid.SimulatedSamples + (Grid.Sleeping ? " (still)" : " (flowing)"));
			list.Add("dungeons in the world (not in the sky): room volumes=" + DungeonVolumes.Count + ", zones where they reach sea level=" + DungeonVolumes.WaterZones.Count);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				list.Add("no local player");
				return list;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			if (DungeonVolumes.Contains(position, 0.3f))
			{
				list.Add("player is inside a dungeon room: always dry here");
			}
			Vector2s zone = ZoneSystem.GetZone(position);
			FloodPage floodPage2 = Grid.Page(zone.x, zone.y);
			if (floodPage2 == null)
			{
				list.Add("zone " + zone.x + "," + zone.y + ": not tracked");
				return list;
			}
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			float num6 = 0f;
			for (int i = 0; i < 4225; i++)
			{
				if (floodPage2.Reclaimed[i])
				{
					num5++;
				}
				if (floodPage2.IsSource(i))
				{
					if (floodPage2.Ground[i] < 0f)
					{
						num2++;
					}
				}
				else if (floodPage2.IsNode(i))
				{
					if (floodPage2.Depth[i] > 0.005f)
					{
						num4++;
					}
					else
					{
						num3++;
					}
					if (FloodPage.IsHome(i))
					{
						num6 += floodPage2.Depth[i];
					}
				}
			}
			bindings.TryGetValue(FloodGrid.Key(zone.x, zone.y), out var value);
			list.Add("zone " + zone.x + "," + zone.y + ": local water=" + floodPage2.Custom + ", simulated here=" + floodPage2.Authority + ", record=" + ((value == null || !((Object)(object)value.Record != (Object)null)) ? "none" : (value.Record.Owned ? "mine" : "remote")) + ", mesh shown=" + (value?.View.Shown ?? false) + ", water triangles=" + (value?.View.TriangleCount ?? 0));
			list.Add("samples: sea=" + num2 + " dry pit=" + num3 + " flooded pit=" + num4 + " reclaimed=" + num5 + ", water in pits=" + num6.ToString("F1") + " m3");
			float waterLevel = ZoneSystem.instance.m_waterLevel;
			int num7 = Mathf.Clamp(Mathf.RoundToInt(position.x - (float)floodPage2.OriginX), 0, 64);
			int num8 = Mathf.Clamp(Mathf.RoundToInt(position.z - (float)floodPage2.OriginZ), 0, 64);
			int num9 = num8 * 65 + num7;
			list.Add("nearest sample " + (floodPage2.OriginX + num7) + "," + (floodPage2.OriginZ + num8) + ": " + Kind(floodPage2, num9) + ", ground " + (waterLevel + floodPage2.Ground[num9]).ToString("F2") + ", original " + (waterLevel + floodPage2.Original[num9]).ToString("F2") + (floodPage2.IsNode(num9) ? (", water depth " + floodPage2.Depth[num9].ToString("F2")) : ""));
			bool wet;
			float level;
			string text = ((!Grid.Query(position.x, position.z, out wet, out level)) ? "vanilla" : (wet ? ("water at " + (waterLevel + level).ToString("F2")) : "dry"));
			list.Add("player y " + position.y.ToString("F2") + ": local water=" + text + ", liquid level seen by the game=" + Floating.GetLiquidLevel(position, 1f, (LiquidType)10).ToString("F2"));
			return list;
		}

		private static string Kind(FloodPage p, int i)
		{
			if (p.IsSource(i))
			{
				if (!(p.Ground[i] < 0f))
				{
					return "raised sea floor";
				}
				return "sea";
			}
			if (p.IsNode(i))
			{
				if (!(p.Depth[i] > 0.005f))
				{
					return "dry pit";
				}
				return "flooded pit";
			}
			if (!p.Reclaimed[i])
			{
				return "land";
			}
			return "reclaimed land";
		}
	}
	internal static class DungeonVolumes
	{
		private struct Volume
		{
			internal Vector3 Center;

			internal Vector3 Half;

			internal Vector3 Right;

			internal Vector3 Forward;

			internal bool Contains(Vector3 p, float margin)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//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_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: 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)
				Vector3 val = p - Center;
				if (Mathf.Abs(val.y) <= Half.y + margin && Mathf.Abs(val.x * Right.x + val.z * Right.z) <= Half.x + margin)
				{
					return Mathf.Abs(val.x * Forward.x + val.z * Forward.z) <= Half.z + margin;
				}
				return false;
			}

			internal void Extent(out float minX, out float maxX, out float minZ, out float maxZ)
			{
				float num = Mathf.Abs(Right.x) * Half.x + Mathf.Abs(Forward.x) * Half.z;
				float num2 = Mathf.Abs(Right.z) * Half.x + Mathf.Abs(Forward.z) * Half.z;
				minX = Center.x - num;
				maxX = Center.x + num;
				minZ = Center.z - num2;
				maxZ = Center.z + num2;
			}
		}

		private const float SkyInteriors = 3000f;

		private const float WaterBand = 2f;

		private static readonly Dictionary<GameObject, List<Volume>> owners = new Dictionary<GameObject, List<Volume>>();

		private static readonly List<Volume> all = new List<Volume>();

		private static readonly Dictionary<long, List<int>> buckets = new Dictionary<long, List<int>>();

		internal static readonly HashSet<long> WaterZones = new HashSet<long>();

		internal static bool Active;

		internal static int Count => all.Count;

		internal static void Clear()
		{
			owners.Clear();
			all.Clear();
			buckets.Clear();
			WaterZones.Clear();
		}

		private static int Zone(float v)
		{
			return Mathf.FloorToInt((v + 32f) / 64f);
		}

		internal static bool Contains(Vector3 p, float margin)
		{
			//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_0056: Unknown result type (might be due to invalid IL or missing references)
			if (all.Count == 0 || !buckets.TryGetValue(FloodGrid.Key(Zone(p.x), Zone(p.z)), out var value))
			{
				return false;
			}
			foreach (int item in value)
			{
				if (all[item].Contains(p, margin))
				{
					return true;
				}
			}
			return false;
		}

		internal static void FromGenerator(DungeonGenerator generator)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)generator).transform.position.y > 3000f)
			{
				return;
			}
			List<Volume> list = new List<Volume>();
			Room[] componentsInChildren = ((Component)generator).GetComponentsInChildren<Room>(true);
			foreach (Room val in componentsInChildren)
			{
				if (((Vector3Int)(ref val.m_size)).x != 0 && ((Vector3Int)(ref val.m_size)).z != 0)
				{
					list.Add(Box(((Component)val).transform.position, new Vector3((float)((Vector3Int)(ref val.m_size)).x, (float)((Vector3Int)(ref val.m_size)).y, (float)((Vector3Int)(ref val.m_size)).z) * 0.5f, ((Component)val).transform.forward));
				}
			}
			Register(((Component)generator).gameObject, list);
		}

		internal static void FromLocation(Location location)
		{
			//IL_003a: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00a8: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: 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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0121: 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_0133: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			if (!location.m_hasInterior)
			{
				return;
			}
			Transform val = (((Object)(object)location.m_interiorTransform != (Object)null) ? location.m_interiorTransform : ((Component)location).transform.Find("Interior"));
			if ((Object)(object)val == (Object)null || val.position.y > 3000f || (Object)(object)((Component)val).GetComponentInChildren<DungeonGenerator>(true) != (Object)null)
			{
				return;
			}
			List<Volume> list = new List<Volume>();
			Matrix4x4 worldToLocalMatrix = val.worldToLocalMatrix;
			foreach (Transform item in val)
			{
				Transform val2 = item;
				if (!((Component)val2).gameObject.activeInHierarchy || (Object)(object)((Component)val2).GetComponent<Teleport>() != (Object)null)
				{
					continue;
				}
				bool flag = false;
				Vector3 val3 = Vector3.positiveInfinity;
				Vector3 val4 = Vector3.negativeInfinity;
				MeshFilter[] componentsInChildren = ((Component)val2).GetComponentsInChildren<MeshFilter>();
				foreach (MeshFilter val5 in componentsInChildren)
				{
					Mesh sharedMesh = val5.sharedMesh;
					MeshRenderer component = ((Component)val5).GetComponent<MeshRenderer>();
					if (!((Object)(object)sharedMesh == (Object)null) && !((Object)(object)component == (Object)null) && ((Renderer)component).enabled)
					{
						Matrix4x4 val6 = worldToLocalMatrix * ((Component)val5).transform.localToWorldMatrix;
						Bounds bounds = sharedMesh.bounds;
						for (int j = 0; j < 8; j++)
						{
							Vector3 val7 = ((Matrix4x4)(ref val6)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f)));
							val3 = Vector3.Min(val3, val7);
							val4 = Vector3.Max(val4, val7);
						}
						flag = true;
					}
				}
				if (flag)
				{
					list.Add(Box(val.TransformPoint((val3 + val4) * 0.5f), (val4 - val3) * 0.5f, val.forward));
				}
			}
			Register(((Component)location).gameObject, list);
		}

		private static Volume Box(Vector3 center, Vector3 half, Vector3 forward)
		{
			//IL_0023: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			forward.y = 0f;
			forward = ((((Vector3)(ref forward)).sqrMagnitude < 1E-06f) ? Vector3.forward : ((Vector3)(ref forward)).normalized);
			return new Volume
			{
				Center = center,
				Half = half,
				Forward = forward,
				Right = new Vector3(forward.z, 0f, 0f - forward.x)
			};
		}

		private static void Register(GameObject owner, List<Volume> list)
		{
			if (list.Count == 0)
			{
				Remove(owner);
				return;
			}
			owners[owner] = list;
			Rebuild();
		}

		internal static void Remove(GameObject owner)
		{
			if (owners.Remove(owner))
			{
				Rebuild();
			}
		}

		private static void Rebuild()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			all.Clear();
			buckets.Clear();
			WaterZones.Clear();
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			foreach (List<Volume> value2 in owners.Values)
			{
				foreach (Volume item in value2)
				{
					int count = all.Count;
					all.Add(item);
					item.Extent(out var minX, out var maxX, out var minZ, out var maxZ);
					bool flag = item.Center.y - item.Half.y < num + 2f && item.Center.y + item.Half.y > num - 2f;
					for (int i = Zone(minX - 0.5f); i <= Zone(maxX + 0.5f); i++)
					{
						for (int j = Zone(minZ - 0.5f); j <= Zone(maxZ + 0.5f); j++)
						{
							long num2 = FloodGrid.Key(i, j);
							if (!buckets.TryGetValue(num2, out var value))
							{
								buckets.Add(num2, value = new List<int>());
							}
							value.Add(count);
							if (flag)
							{
								WaterZones.Add(num2);
							}
						}
					}
				}
			}
			DryPitsSystem.DungeonsChanged();
		}
	}
	internal sealed class FloodPage
	{
		internal const int Size = 65;

		internal const int Count = 4225;

		internal readonly int Zx;

		internal readonly int Zz;

		internal readonly int OriginX;

		internal readonly int OriginZ;

		internal readonly float[] Original = new float[4225];

		internal readonly float[] Ground = new float[4225];

		internal readonly float[] Depth = new float[4225];

		internal readonly float[] Flow = new float[16900];

		internal readonly bool[] Reclaimed = new bool[4225];

		internal bool HasGround;

		internal bool Authority;

		internal bool Custom;

		internal bool PersistDirty;

		internal bool Dungeon;

		internal bool Loaded;

		internal ZoneState Pending;

		internal int Revision;

		internal FloodPage(int zx, int zz)
		{
			Zx = zx;
			Zz = zz;
			OriginX = zx * 64 - 32;
			OriginZ = zz * 64 - 32;
		}

		internal bool IsSource(int i)
		{
			if (!Reclaimed[i])
			{
				return Original[i] <= 0f;
			}
			return false;
		}

		internal bool IsNode(int i)
		{
			if (Reclaimed[i] || Original[i] > 0f)
			{
				return Ground[i] < 0f;
			}
			return false;
		}

		internal static bool IsHome(int i)
		{
			if (i % 65 < 64)
			{
				return i / 65 < 64;
			}
			return false;
		}
	}
	internal static class FloodMath
	{
		internal const float Gravity = 9.81f;

		internal const float Still = 2E-06f;

		internal const float Overshoot = 0.05f;

		internal static float MaxDt = 0.02f;

		internal static float Damping = 0.5f;

		internal static float Share = 0.5f;

		internal static float Pipe(float flow, float dt, float from, float to, float crest)
		{
			float num = from - crest;
			float num2 = from - to;
			if (num <= 0f || num2 <= 0f)
			{
				return 0f;
			}
			flow = flow * Math.Max(0f, 1f - Damping * dt) + dt * 9.81f * num2 * num;
			flow = Math.Min(flow, num2 * Share / dt);
			if (!(flow * dt < 2E-06f))
			{
				return flow;
			}
			return 0f;
		}
	}
	internal sealed class ZoneState
	{
		internal const short Dry = short.MinValue;

		private const int Version = 1;

		internal readonly short[] Levels = new short[4225];

		internal readonly bool[] Reclaimed = new bool[4225];

		internal bool Trivial
		{
			get
			{
				for (int i = 0; i < 4225; i++)
				{
					if (Levels[i] != short.MinValue || Reclaimed[i])
					{
						return false;
					}
				}
				return true;
			}
		}

		internal static ZoneState Capture(FloodPage p)
		{
			ZoneState zoneState = new ZoneState();
			for (int i = 0; i < 4225; i++)
			{
				zoneState.Reclaimed[i] = p.Reclaimed[i];
				zoneState.Levels[i] = ((p.IsNode(i) && p.Depth[i] > 0.0005f) ? ((short)Math.Max(-32767, Math.Min(0, (int)Math.Round((p.Ground[i] + p.Depth[i]) * 1000f)))) : short.MinValue);
			}
			return zoneState;
		}

		internal float DepthAt(int i, float ground)
		{
			if (Levels[i] == short.MinValue || ground >= 0f)
			{
				return 0f;
			}
			return Math.Max(0f, Math.Min(0f - ground, (float)Levels[i] / 1000f - ground));
		}

		internal byte[] Serialize()
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(1);
			binaryWriter.Write(65);
			short[] levels = Levels;
			foreach (short value in levels)
			{
				binaryWriter.Write(value);
			}
			byte b = 0;
			for (int j = 0; j < 4225; j++)
			{
				if (Reclaimed[j])
				{
					b |= (byte)(1 << (j & 7));
				}
				if ((j & 7) == 7 || j == 4224)
				{
					binaryWriter.Write(b);
					b = 0;
				}
			}
			binaryWriter.Flush();
			return memoryStream.ToArray();
		}

		internal static ZoneState Deserialize(byte[] data)
		{
			if (data == null || data.Length < 8)
			{
				return null;
			}
			try
			{
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(data));
				if (binaryReader.ReadInt32() != 1 || binaryReader.ReadInt32() != 65)
				{
					return null;
				}
				ZoneState zoneState = new ZoneState();
				for (int i = 0; i < 4225; i++)
				{
					zoneState.Levels[i] = Math.Min((short)0, binaryReader.ReadInt16());
				}
				byte b = 0;
				for (int j = 0; j < 4225; j++)
				{
					if ((j & 7) == 0)
					{
						b = binaryReader.ReadByte();
					}
					zoneState.Reclaimed[j] = (b & (1 << (j & 7))) != 0;
				}
				return zoneState;
			}
			catch (EndOfStreamException)
			{
				return null;
			}
		}
	}
	internal sealed class FloodGrid
	{
		private sealed class Node
		{
			internal FloodPage Page;

			internal int Index;

			internal float Ground;

			internal float Published;

			internal readonly FloodPage[] Next = new FloodPage[4];

			internal readonly int[] NextIndex = new int[4];

			internal readonly byte[] Kind = new byte[4];

			internal readonly float[] Crest = new float[4];

			internal readonly float[] BackCrest = new float[4];
		}

		private static readonly int[] StepX = new int[4] { -1, 1, 0, 0 };

		private static readonly int[] StepZ = new int[4] { 0, 0, -1, 1 };

		private readonly Dictionary<long, FloodPage> pages = new Dictionary<long, FloodPage>();

		private readonly Dictionary<long, ZoneState> saved = new Dictionary<long, ZoneState>();

		private readonly List<Node> nodes = new List<Node>();

		private readonly HashSet<FloodPage> touched = new HashSet<FloodPage>();

		private readonly FloodPage[] copyPages = new FloodPage[4];

		private readonly int[] copyIndex = new int[4];

		private int nodeCount;

		private bool nodesDirty = true;

		private bool sleeping;

		internal int MaxWork = 250000;

		internal IEnumerable<FloodPage> Pages => pages.Values;

		internal int SimulatedSamples => nodeCount;

		internal bool Sleeping => sleeping;

		internal static long Key(int zx, int zz)
		{
			return ((long)zx << 32) | (uint)zz;
		}

		internal static int ZoneOf(int sample)
		{
			int num = sample + 32;
			if (num < 0)
			{
				return -((63 - num) / 64);
			}
			return num / 64;
		}

		internal FloodPage Page(int zx, int zz)
		{
			if (!pages.TryGetValue(Key(zx, zz), out var value) || !value.HasGround)
			{
				return null;
			}
			return value;
		}

		internal void Clear()
		{
			pages.Clear();
			saved.Clear();
			touched.Clear();
			nodeCount = 0;
			Wake();
		}

		private void Wake()
		{
			nodesDirty = true;
			sleeping = false;
		}

		internal void SetAuthority(FloodPage p, bool authority)
		{
			authority &= p.Loaded;
			if (p.Authority != authority)
			{
				p.Authority = authority;
				Wake();
			}
		}

		internal bool TryHome(int x, int z, out FloodPage page, out int index)
		{
			page = Page(ZoneOf(x), ZoneOf(z));
			index = ((page == null) ? (-1) : ((z - page.OriginZ) * 65 + x - page.OriginX));
			return page != null;
		}

		internal bool TrySample(int x, int z, out FloodPage page, out int index)
		{
			int num = Copies(x, z);
			page = ((num > 0) ? copyPages[0] : null);
			index = ((num > 0) ? copyIndex[0] : (-1));
			return num > 0;
		}

		private int Copies(int x, int z)
		{
			int num = ZoneOf(x);
			int num2 = ZoneOf(z);
			int num3 = 0;
			bool flag = x == num * 64 - 32;
			bool flag2 = z == num2 * 64 - 32;
			for (int i = 0; i < 4; i++)
			{
				int num4 = i & 1;
				int num5 = i >> 1;
				if ((num4 != 1 || flag) && (num5 != 1 || flag2))
				{
					FloodPage floodPage = Page(num - num4, num2 - num5);
					if (floodPage != null)
					{
						copyPages[num3] = floodPage;
						copyIndex[num3++] = (z - floodPage.OriginZ) * 65 + x - floodPage.OriginX;
					}
				}
			}
			return num3;
		}

		private void SetDepth(int x, int z, float depth)
		{
			int num = Copies(x, z);
			for (int i = 0; i < num; i++)
			{
				FloodPage floodPage = copyPages[i];
				int num2 = copyIndex[i];
				if (floodPage.Depth[num2] != depth)
				{
					floodPage.Depth[num2] = depth;
					floodPage.Revision++;
					floodPage.PersistDirty = true;
					touched.Add(floodPage);
				}
			}
		}

		internal FloodPage UpdateGround(int zx, int zz, float[] ground, float[] original, bool authority, bool ready = true)
		{
			long key = Key(zx, zz);
			if (!pages.TryGetValue(key, out var value))
			{
				pages.Add(key, value = new FloodPage(zx, zz));
			}
			if (!value.HasGround)
			{
				saved.TryGetValue(key, out value.Pending);
			}
			Array.Copy(ground, value.Ground, 4225);
			Array.Copy(original, value.Original, 4225);
			value.HasGround = true;
			touched.Clear();
			if (!value.Loaded && ready)
			{
				value.Loaded = true;
				if (value.Pending != null)
				{
					Load(value, value.Pending);
				}
				else
				{
					AdoptEdges(value);
				}
				value.Pending = null;
			}
			value.Authority = authority && value.Loaded;
			if (value.Authority)
			{
				Reclaim(value);
			}
			if (value.Loaded)
			{
				Clamp(value);
			}
			value.Revision++;
			touched.Add(value);
			RefreshTouched();
			Wake();
			return value;
		}

		internal void ApplyRecord(int zx, int zz, ZoneState state)
		{
			Remember(Key(zx, zz), state);
			FloodPage floodPage = Page(zx, zz);
			if (floodPage != null)
			{
				if (!floodPage.Loaded)
				{
					floodPage.Pending = state;
					return;
				}
				touched.Clear();
				Load(floodPage, state);
				Clamp(floodPage);
				floodPage.Revision++;
				touched.Add(floodPage);
				RefreshTouched();
				Wake();
			}
		}

		internal void SetDungeon(int zx, int zz, bool dungeon)
		{
			FloodPage floodPage = Page(zx, zz);
			if (floodPage != null && floodPage.Dungeon != dungeon)
			{
				floodPage.Dungeon = dungeon;
				touched.Clear();
				floodPage.Revision++;
				touched.Add(floodPage);
				RefreshTouched();
			}
		}

		internal void Remove(int zx, int zz)
		{
			long key = Key(zx, zz);
			if (pages.TryGetValue(key, out var value))
			{
				if (value.Loaded)
				{
					Remember(key, ZoneState.Capture(value));
				}
				else if (value.Pending != null)
				{
					Remember(key, value.Pending);
				}
				pages.Remove(key);
				Wake();
			}
		}

		private void Remember(long key, ZoneState state)
		{
			if (state.Trivial)
			{
				saved.Remove(key);
			}
			else
			{
				saved[key] = state;
			}
		}

		private void Load(FloodPage p, ZoneState state)
		{
			for (int i = 0; i < 4225; i++)
			{
				if (state.Reclaimed[i])
				{
					p.Reclaimed[i] = true;
				}
			}
			for (int j = 0; j < 4225; j++)
			{
				p.Depth[j] = (p.IsNode(j) ? state.DepthAt(j, p.Ground[j]) : 0f);
			}
			AdoptEdges(p);
		}

		private void AdoptEdges(FloodPage p)
		{
			for (int i = 0; i < 4225; i++)
			{
				int num = i % 65;
				int num2 = i / 65;
				if (num != 0 && num != 64 && num2 != 0 && num2 != 64)
				{
					continue;
				}
				int x = p.OriginX + num;
				int z = p.OriginZ + num2;
				int num3 = Copies(x, z);
				if (num3 < 2)
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < num3; j++)
				{
					flag |= copyPages[j].Reclaimed[copyIndex[j]];
				}
				for (int k = 0; k < num3; k++)
				{
					if (flag && !copyPages[k].Reclaimed[copyIndex[k]])
					{
						copyPages[k].Reclaimed[copyIndex[k]] = true;
						copyPages[k].Revision++;
						touched.Add(copyPages[k]);
					}
				}
				if (TryHome(x, z, out var page, out var index) && page != p)
				{
					if (page.Loaded)
					{
						p.Depth[i] = (page.IsNode(index) ? page.Depth[index] : 0f);
					}
				}
				else
				{
					SetDepth(x, z, p.Depth[i]);
				}
			}
		}

		private void Reclaim(FloodPage p)
		{
			for (int i = 0; i < 4225; i++)
			{
				if (FloodPage.IsHome(i) && !p.Reclaimed[i] && !(p.Original[i] > 0f) && !(p.Ground[i] <= 0.05f))
				{
					int x = p.OriginX + i % 65;
					int z = p.OriginZ + i / 65;
					int num = Copies(x, z);
					for (int j = 0; j < num; j++)
					{
						FloodPage floodPage = copyPages[j];
						floodPage.Reclaimed[copyIndex[j]] = true;
						floodPage.PersistDirty = true;
						floodPage.Revision++;
						touched.Add(floodPage);
					}
					SetDepth(x, z, 0f);
				}
			}
		}

		private static void Clamp(FloodPage p)
		{
			for (int i = 0; i < 4225; i++)
			{
				float num = (p.IsNode(i) ? (0f - p.Ground[i]) : 0f);
				float num2 = p.Depth[i];
				float num3 = ((num2 < 0f) ? 0f : ((num2 > num) ? num : num2));
				if (num3 != num2)
				{
					p.Depth[i] = num3;
					p.PersistDirty = true;
					p.Revision++;
				}
			}
		}

		private void RefreshTouched()
		{
			foreach (FloodPage item in touched)
			{
				bool flag = false;
				for (int i = 0; i < 4225; i++)
				{
					if (flag)
					{
						break;
					}
					flag = item.IsNode(i) && item.Ground[i] + item.Depth[i] < -0.02f;
				}
				item.Custom = flag || item.Dungeon;
			}
			touched.Clear();
		}

		private void RebuildNodes()
		{
			nodesDirty = false;
			nodeCount = 0;
			foreach (FloodPage value in pages.Values)
			{
				if (!value.HasGround || !value.Authority)
				{
					continue;
				}
				for (int i = 0; i < 64; i++)
				{
					for (int j = 0; j < 64; j++)
					{
						int num = i * 65 + j;
						if (!value.IsNode(num))
						{
							continue;
						}
						if (nodeCount == nodes.Count)
						{
							nodes.Add(new Node());
						}
						Node node = nodes[nodeCount++];
						node.Page = value;
						node.Index = num;
						node.Ground = value.Ground[num];
						node.Published = value.Depth[num];
						for (int k = 0; k < 4; k++)
						{
							node.Kind[k] = 0;
							int x = value.OriginX + j + StepX[k];
							int z = value.OriginZ + i + StepZ[k];
							if (!TrySample(x, z, out var page, out var index))
							{
								continue;
							}
							float num2 = page.Ground[index];
							float val = (node.Ground + num2) * 0.5f;
							if (page.IsNode(index))
							{
								if (!TryHome(x, z, out page, out index) || !page.Authority)
								{
									continue;
								}
								node.Kind[k] = 1;
							}
							else
							{
								if (!page.IsSource(index) || !(num2 < 0f))
								{
									continue;
								}
								node.Kind[k] = 2;
							}
							node.Next[k] = page;
							node.NextIndex[k] = index;
							node.Crest[k] = Math.Max(val, num2);
							node.BackCrest[k] = Math.Max(val, node.Ground);
						}
						for (int l = 0; l < 4; l++)
						{
							if (node.Kind[l] == 0)
							{
								value.Flow[num * 4 + l] = 0f;
							}
						}
					}
				}
			}
		}

		internal void Step(float seconds)
		{
			if (sleeping || seconds <= 0f)
			{
				return;
			}
			if (nodesDirty)
			{
				RebuildNodes();
			}
			if (nodeCount == 0)
			{
				sleeping = true;
				return;
			}
			int num = Math.Min((int)Math.Ceiling(seconds / FloodMath.MaxDt), Math.Max(1, MaxWork / nodeCount));
			float dt = Math.Min(FloodMath.MaxDt, seconds / (float)num);
			bool flag = false;
			for (int i = 0; i < num; i++)
			{
				flag |= Substep(dt);
			}
			Publish();
			if (!flag)
			{
				sleeping = true;
			}
		}

		private bool Substep(float dt)
		{
			bool flag = false;
			for (int i = 0; i < nodeCount; i++)
			{
				Node node = nodes[i];
				FloodPage page = node.Page;
				int num = node.Index * 4;
				float num2 = page.Depth[node.Index];
				float num3 = node.Ground + num2;
				for (int j = 0; j < 4; j++)
				{
					float num4 = 0f;
					int num5 = node.Kind[j];
					if (num5 != 0)
					{
						FloodPage floodPage = node.Next[j];
						int num6 = node.NextIndex[j];
						if (num2 > 0f)
						{
							num4 = FloodMath.Pipe(page.Flow[num + j], dt, num3, (num5 == 1) ? (floodPage.Ground[num6] + floodPage.Depth[num6]) : 0f, node.Crest[j]);
						}
						if (num5 == 2)
						{
							int num7 = num6 * 4 + (j ^ 1);
							float num8 = FloodMath.Pipe(floodPage.Flow[num7], dt, 0f, num3, node.BackCrest[j]);
							floodPage.Flow[num7] = num8;
							flag = flag || num8 > 0f;
						}
					}
					page.Flow[num + j] = num4;
					flag = flag || num4 > 0f;
				}
			}
			if (!flag)
			{
				return false;
			}
			for (int k = 0; k < nodeCount; k++)
			{
				Node node2 = nodes[k];
				float[] flow = node2.Page.Flow;
				int num9 = node2.Index * 4;
				float num10 = (flow[num9] + flow[num9 + 1] + flow[num9 + 2] + flow[num9 + 3]) * dt;
				float num11 = node2.Page.Depth[node2.Index];
				if (!(num10 <= num11))
				{
					float num12 = ((num10 > 0f) ? (num11 / num10) : 0f);
					flow[num9] *= num12;
					flow[num9 + 1] *= num12;
					flow[num9 + 2] *= num12;
					flow[num9 + 3] *= num12;
				}
			}
			for (int l = 0; l < nodeCount; l++)
			{
				Node node3 = nodes[l];
				FloodPage page2 = node3.Page;
				int num13 = node3.Index * 4;
				float num14 = 0f - (page2.Flow[num13] + page2.Flow[num13 + 1] + page2.Flow[num13 + 2] + page2.Flow[num13 + 3]);
				for (int m = 0; m < 4; m++)
				{
					if (node3.Kind[m] != 0)
					{
						num14 += node3.Next[m].Flow[node3.NextIndex[m] * 4 + (m ^ 1)];
					}
				}
				float num15 = page2.Depth[node3.Index] + num14 * dt;
				float num16 = 0.05f - node3.Ground;
				page2.Depth[node3.Index] = ((num15 < 0f) ? 0f : ((num15 > num16) ? num16 : num15));
			}
			return true;
		}

		private void Publish()
		{
			touched.Clear();
			for (int i = 0; i < nodeCount; i++)
			{
				Node node = nodes[i];
				FloodPage page = node.Page;
				int index = node.Index;
				float num = page.Depth[index];
				if (!(Math.Abs(num - node.Published) < 0.0005f) || (num == 0f && node.Published != 0f))
				{
					node.Published = num;
					page.Revision++;
					page.PersistDirty = true;
					touched.Add(page);
					SetDepth(page.OriginX + index % 65, page.OriginZ + index / 65, num);
				}
			}
			RefreshTouched();
		}

		internal static float Mask(FloodPage p, int i, out bool wet, out float level)
		{
			float num = p.Ground[i];
			if (p.IsSource(i))
			{
				wet = num < 0f;
				level = 0f;
				return num;
			}
			if (p.IsNode(i))
			{
				float num2 = p.Depth[i];
				if (num2 > 0.005f)
				{
					wet = true;
					level = num + num2;
					return 0f - num2;
				}
				wet = false;
				level = num;
				return 1f;
			}
			wet = false;
			level = 0f;
			return Math.Max(num, 0.01f);
		}

		internal static int Classify(FloodPage p, int i, out float level)
		{
			Mask(p, i, out var wet, out level);
			if (!wet)
			{
				if (!p.IsNode(i))
				{
					return 0;
				}
				return 2;
			}
			return 1;
		}

		internal bool Query(float x, float z, out bool wet, out float level)
		{
			wet = false;
			level = 0f;
			int zx = (int)Math.Floor((x + 32f) / 64f);
			int zz = (int)Math.Floor((z + 32f) / 64f);
			if (!pages.TryGetValue(Key(zx, zz), out var value) || !value.HasGround || !value.Custom)
			{
				return false;
			}
			float num = x - (float)value.OriginX;
			float num2 = z - (float)value.OriginZ;
			int num3 = Math.Min(63, Math.Max(0, (int)Math.Floor(num)));
			int num4 = Math.Min(63, Math.Max(0, (int)Math.Floor(num2)));
			float num5 = Math.Min(1f, Math.Max(0f, num - (float)num3));
			float num6 = Math.Min(1f, Math.Max(0f, num2 - (float)num4));
			float num7 = 0f;
			float num8 = 0f;
			float num9 = 0f;
			for (int i = 0; i < 4; i++)
			{
				int num10 = i & 1;
				int num11 = i >> 1;
				int i2 = (num4 + num11) * 65 + num3 + num10;
				float num12 = ((num10 == 1) ? num5 : (1f - num5)) * ((num11 == 1) ? num6 : (1f - num6));
				num7 += num12 * Mask(value, i2, out var wet2, out var level2);
				if (wet2)
				{
					num8 += num12;
					num9 += num12 * level2;
				}
			}
			if (num7 > -0.002f || num8 <= 0.0001f)
			{
				return true;
			}
			wet = true;
			level = num9 / num8;
			return true;
		}
	}
	internal static class Guard
	{
		private static float nextReport;

		internal static void Report(string where, Exception e)
		{
			if (!(Time.realtimeSinceStartup < nextReport))
			{
				nextReport = Time.realtimeSinceStartup + 10f;
				Plugin.Error("error in " + where + ": " + e);
			}
		}
	}
	[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
	internal static class CaptureOriginalHeights
	{
		private static void Prefix(float[] baseHeights, Heightmap hm)
		{
			try
			{
				DryPitsSystem.CaptureBase(hm, baseHeights);
			}
			catch (Exception e)
			{
				Guard.Report("terrain capture", e);
			}
		}
	}
	[HarmonyPatch(typeof(Heightmap), "RebuildCollisionMesh")]
	internal static class TerrainRebuilt
	{
		private static void Postfix(Heightmap __instance)
		{
			try
			{
				DryPitsSystem.HeightsChanged(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("terrain update", e);
			}
		}
	}
	[HarmonyPatch(typeof(Heightmap), "OnDestroy")]
	internal static class TerrainDestroyed
	{
		private static void Prefix(Heightmap __instance)
		{
			try
			{
				DryPitsSystem.HeightmapDestroyed(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("zone unload", e);
			}
		}
	}
	[HarmonyPatch(typeof(WaterVolume), "GetWaterSurface")]
	internal static class LocalWaterSurface
	{
		private static void Postfix(WaterVolume __instance, Vector3 point, ref float __result)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.m_heightmap != null)
			{
				bool wet;
				float level;
				if (DungeonVolumes.Active && DungeonVolumes.Count > 0 && DungeonVolumes.Contains(point, 0.3f))
				{
					__result = -10000f;
				}
				else if (DryPitsSystem.QueryActive && DryPitsSystem.Grid.Query(point.x, point.z, out wet, out level))
				{
					__result = (wet ? (__result + level) : (-10000f));
				}
			}
		}
	}
	[HarmonyPatch(typeof(DungeonGenerator), "Generate", new Type[]
	{
		typeof(int),
		typeof(SpawnMode)
	})]
	internal static class DungeonGenerated
	{
		private static void Postfix(DungeonGenerator __instance, SpawnMode mode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)mode != 0)
			{
				return;
			}
			try
			{
				DungeonVolumes.FromGenerator(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("dungeon rooms", e);
			}
		}
	}
	[HarmonyPatch(typeof(DungeonGenerator), "Spawn")]
	internal static class DungeonLoaded
	{
		private static void Postfix(DungeonGenerator __instance)
		{
			try
			{
				DungeonVolumes.FromGenerator(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("dungeon rooms", e);
			}
		}
	}
	[HarmonyPatch(typeof(DungeonGenerator), "OnDestroy")]
	internal static class DungeonUnloaded
	{
		private static void Prefix(DungeonGenerator __instance)
		{
			try
			{
				DungeonVolumes.Remove(((Component)__instance).gameObject);
			}
			catch (Exception e)
			{
				Guard.Report("dungeon unload", e);
			}
		}
	}
	[HarmonyPatch(typeof(Location), "Awake")]
	internal static class LocationLoaded
	{
		private static void Postfix(Location __instance)
		{
			try
			{
				DungeonVolumes.FromLocation(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("location interior", e);
			}
		}
	}
	[HarmonyPatch(typeof(Location), "OnDestroy")]
	internal static class LocationUnloaded
	{
		private static void Prefix(Location __instance)
		{
			try
			{
				DungeonVolumes.Remove(((Component)__instance).gameObject);
			}
			catch (Exception e)
			{
				Guard.Report("location unload", e);
			}
		}
	}
	[HarmonyPatch(typeof(BaseAI), "IsValidRandomMovePoint")]
	internal static class DryDungeonFloors
	{
		private static void Prefix(BaseAI __instance, Vector3 point, out bool __state)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			if (!__instance.m_avoidWater || !DungeonVolumes.Active || DungeonVolumes.Count == 0)
			{
				return;
			}
			try
			{
				if (DungeonVolumes.Contains(point, 1f))
				{
					__instance.m_avoidWater = false;
					__state = true;
				}
			}
			catch (Exception e)
			{
				Guard.Report("dungeon wander", e);
			}
		}

		private static void Postfix(BaseAI __instance, bool __state)
		{
			if (__state)
			{
				__instance.m_avoidWater = true;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class SessionStart
	{
		private static void Postfix(ZNetScene __instance)
		{
			try
			{
				DryPitsSystem.ResetSession();
				WaterRecord.RegisterPrefab(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("session start", e);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "OnDestroy")]
	internal static class SessionEnd
	{
		private static void Prefix()
		{
			try
			{
				DryPitsSystem.ResetSession();
			}
			catch (Exception e)
			{
				Guard.Report("session end", e);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetView), "ResetZDO")]
	internal static class SaveBeforeUnload
	{
		private static void Prefix(ZNetView __instance)
		{
			try
			{
				DryPitsSystem.BeforeViewReset(__instance);
			}
			catch (Exception e)
			{
				Guard.Report("record unload", e);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "SaveWorld")]
	internal static class SaveBeforeWorldSave
	{
		private static void Prefix()
		{
			try
			{
				DryPitsSystem.FlushAll();
			}
			catch (Exception e)
			{
				Guard.Report("world save", e);
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	internal static class SaveBeforeShutdown
	{
		private static void Prefix()
		{
			try
			{
				DryPitsSystem.FlushAll();
			}
			catch (Exception e)
			{
				Guard.Report("shutdown", e);
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	internal static class ConsoleRegistration
	{
		private static void Postfix()
		{
			try
			{
				DryPitsSystem.RegisterCommand();
			}
			catch (Exception e)
			{
				Guard.Report("console", e);
			}
		}
	}
	[BepInPlugin("local.valheim.drypits", "Dry Pits", "0.3.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "local.valheim.drypits";

		public const string Version = "0.3.0";

		internal static Plugin Instance;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> VerboseLog;

		internal static ConfigEntry<float> FillSpeed;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Ground dug below sea level away from the sea stays dry. Turning it off restores vanilla water at once.");
			FillSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Water", "FillSpeedMultiplier", 1f, new ConfigDescription("How fast connected pits fill: 1 = normal, 2 = twice as fast, 0 = paused. The final level stays the same. In multiplayer each zone runs at its owner's setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			VerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLog", false, "Log every zone that switches between vanilla and local water, and every new water record.");
			harmony = new Harmony("local.valheim.drypits");
			harmony.PatchAll();
			if ((bool)AccessTools.Field(typeof(Terminal), "m_terminalInitialized").GetValue(null))
			{
				DryPitsSystem.RegisterCommand();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Dry Pits 0.3.0 ready: dry pits, flooding and dry dungeons. Console: drypits");
		}

		private void Update()
		{
			try
			{
				DryPitsSystem.Tick();
			}
			catch (Exception e)
			{
				Guard.Report("update", e);
			}
		}

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

		internal static void Log(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}

		internal static void Error(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)message);
		}

		internal static void Trace(string message)
		{
			if (VerboseLog.Value)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}
	}
	public sealed class WaterRecord : MonoBehaviour
	{
		internal const string PrefabName = "DryPits_WaterState";

		internal const string PayloadKey = "drypits_state_v1";

		internal static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("DryPits_WaterState");

		private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> namedPrefabs = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");

		internal ZNetView View;

		internal int Zx;

		internal int Zz;

		internal bool Registered;

		internal bool Rejected;

		private uint seenRevision = uint.MaxValue;

		internal bool Valid
		{
			get
			{
				if ((Object)(object)View != (Object)null)
				{
					return View.IsValid();
				}
				return false;
			}
		}

		internal bool Owned
		{
			get
			{
				if (Valid)
				{
					return View.IsOwner();
				}
				return false;
			}
		}

		internal ZDOID Uid => View.GetZDO().m_uid;

		internal static void RegisterPrefab(ZNetScene scene)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			GameObject val = new GameObject("DryPits prefabs");
			val.SetActive(false);
			val.transform.SetParent(((Component)scene).transform, false);
			GameObject val2 = new GameObject("DryPits_WaterState");
			val2.transform.SetParent(val.transform, false);
			val2.AddComponent<ZNetView>().m_persistent = true;
			val2.AddComponent<WaterRecord>();
			namedPrefabs.Invoke(scene)[PrefabHash] = val2;
		}

		private void Awake()
		{
			TryRegister();
		}

		private void Update()
		{
			if (!Registered)
			{
				if (!Rejected)
				{
					TryRegister();
				}
			}
			else if (Valid)
			{
				uint dataRevision = View.GetZDO().DataRevision;
				if (dataRevision != seenRevision)
				{
					seenRevision = dataRevision;
					DryPitsSystem.RecordChanged(this);
				}
			}
		}

		private void OnDestroy()
		{
			DryPitsSystem.UnregisterRecord(this);
		}

		private void TryRegister()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)View == (Object)null)
			{
				View = ((Component)this).GetComponent<ZNetView>();
			}
			if (Valid)
			{
				Vector2s zone = ZoneSystem.GetZone(((Component)this).transform.position);
				Zx = zone.x;
				Zz = zone.y;
				seenRevision = View.GetZDO().DataRevision;
				DryPitsSystem.RegisterRecord(this);
			}
		}

		internal byte[] Read()
		{
			if (!Valid)
			{
				return null;
			}
			return View.GetZDO().GetByteArray("drypits_state_v1", (byte[])null);
		}

		internal void Write(byte[] payload)
		{
			ZDO zDO = View.GetZDO();
			zDO.Set("drypits_state_v1", payload);
			seenRevision = zDO.DataRevision;
		}
	}
	internal sealed class WaterSurfaceView
	{
		private const int S = 65;

		private static readonly List<Vector3> vertices = new List<Vector3>();

		private static readonly List<Vector3> normals = new List<Vector3>();

		private static readonly List<Vector4> tangents = new List<Vector4>();

		private static readonly List<Vector2> uvs = new List<Vector2>();

		private static readonly List<int> triangles = new List<int>();

		private static readonly int[] kinds = new int[4225];

		private static readonly float[] levels = new float[4225];

		private readonly Transform surface;

		private readonly MeshFilter filter;

		private readonly Mesh original;

		private readonly BoxCollider[] boxes;

		private readonly bool[] boxEnabled;

		private Mesh mesh;

		private MeshCollider collider;

		private bool shown;

		private bool cookPending;

		private float nextCook;

		internal bool Shown => shown;

		internal int TriangleCount { get; private set; }

		private WaterSurfaceView(Transform surface, MeshFilter filter)
		{
			this.surface = surface;
			this.filter = filter;
			original = filter.sharedMesh;
			boxes = ((Component)surface).GetComponents<BoxCollider>();
			boxEnabled = new bool[boxes.Length];
		}

		internal static WaterSurfaceView Find(Heightmap hm)
		{
			Transform parent = ((Component)hm).transform.parent;
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			WaterVolume componentInChildren = ((Component)parent).GetComponentInChildren<WaterVolume>(true);
			if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.m_waterSurface == (Object)null || (Object)(object)componentInChildren.m_heightmap != (Object)(object)hm)
			{
				return null;
			}
			MeshFilter component = ((Component)componentInChildren.m_waterSurface).GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null))
			{
				return new WaterSurfaceView(((Component)componentInChildren.m_waterSurface).transform, component);
			}
			return null;
		}

		internal void Show(FloodPage p, float now)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)surface == (Object)null)
			{
				return;
			}
			Build(p);
			if ((Object)(object)mesh == (Object)null)
			{
				mesh = new Mesh
				{
					name = "DryPits water"
				};
				mesh.MarkDynamic();
			}
			mesh.Clear();
			mesh.SetVertices(vertices);
			mesh.SetNormals(normals);
			mesh.SetTangents(tangents);
			mesh.SetUVs(0, uvs);
			mesh.SetTriangles(triangles, 0, false);
			mesh.bounds = new Bounds(Vector3.zero, new Vector3(2.2f, 44f, 2.2f));
			TriangleCount = triangles.Count / 3;
			if (!shown)
			{
				shown = true;
				filter.sharedMesh = mesh;
				for (int i = 0; i < boxes.Length; i++)
				{
					boxEnabled[i] = ((Collider)boxes[i]).enabled;
					((Collider)boxes[i]).enabled = false;
				}
				collider = ((Component)surface).gameObject.AddComponent<MeshCollider>();
				collider.convex = false;
				((Collider)collider).excludeLayers = LayerMask.op_Implicit(-1);
				nextCook = 0f;
			}
			cookPending = true;
			Update(now);
		}

		internal void Update(float now)
		{
			if (shown && cookPending && !(now < nextCook) && !((Object)(object)collider == (Object)null))
			{
				cookPending = false;
				nextCook = now + 1.5f;
				collider.sharedMesh = null;
				((Collider)collider).enabled = TriangleCount > 0;
				if (TriangleCount > 0)
				{
					collider.sharedMesh = mesh;
				}
			}
		}

		internal void Restore()
		{
			if (!shown)
			{
				return;
			}
			shown = false;
			cookPending = false;
			if ((Object)(object)filter != (Object)null)
			{
				filter.sharedMesh = original;
			}
			for (int i = 0; i < boxes.Length; i++)
			{
				if ((Object)(object)boxes[i] != (Object)null)
				{
					((Collider)boxes[i]).enabled = boxEnabled[i];
				}
			}
			if ((Object)(object)collider != (Object)null)
			{
				Object.Destroy((Object)(object)collider);
			}
			collider = null;
		}

		internal void Dispose()
		{
			Restore();
			if ((Object)(object)mesh != (Object)null)
			{
				Object.Destroy((Object)(object)mesh);
			}
			mesh = null;
		}

		private void Build(FloodPage p)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			vertices.Clear();
			normals.Clear();
			tangents.Clear();
			uvs.Clear();
			triangles.Clear();
			for (int i = 0; i < 4225; i++)
			{
				kinds[i] = FloodGrid.Classify(p, i, out levels[i]);
			}
			Matrix4x4 worldToLocalMatrix = surface.worldToLocalMatrix;
			float waterLevel = ZoneSystem.instance.m_waterLevel;
			for (int j = 0; j < 64; j++)
			{
				for (int k = 0; k < 64; k++)
				{
					int num = j * 65 + k;
					int num2 = num + 1;
					int num3 = num + 65;
					int c = num3 + 1;
					Triangle(p, worldToLocalMatrix, waterLevel, num, num3, num2);
					Triangle(p, worldToLocalMatrix, waterLevel, num2, num3, c);
				}
			}
		}

		private void Triangle(FloodPage p, Matrix4x4 toLocal, float sea, int a, int b, int c)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			int num = kinds[a];
			int num2 = kinds[b];
			int num3 = kinds[c];
			if (num == 1 || num2 == 1 || num3 == 1)
			{
				float num4 = float.MinValue;
				if (num == 1)
				{
					num4 = Mathf.Max(num4, levels[a]);
				}
				if (num2 == 1)
				{
					num4 = Mathf.Max(num4, levels[b]);
				}
				if (num3 == 1)
				{
					num4 = Mathf.Max(num4, levels[c]);
				}
				if (!Deep(p, a, num, num4) && !Deep(p, b, num2, num4) && !Deep(p, c, num3, num4))
				{
					Vertex(p, toLocal, sea, a, (num == 1) ? levels[a] : num4);
					Vertex(p, toLocal, sea, b, (num2 == 1) ? levels[b] : num4);
					Vertex(p, toLocal, sea, c, (num3 == 1) ? levels[c] : num4);
				}
			}
		}

		private static bool Deep(FloodPage p, int i, int kind, float top)
		{
			if (kind == 2)
			{
				return p.Ground[i] < top - 0.25f;
			}
			return false;
		}

		private static void Vertex(FloodPage p, Matrix4x4 toLocal, float sea, int i, float level)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Matrix4x4)(ref toLocal)).MultiplyPoint3x4(new Vector3((float)(p.OriginX + i % 65), sea + level, (float)(p.OriginZ + i / 65)));
			triangles.Add(vertices.Count);
			vertices.Add(val);
			normals.Add(Vector3.up);
			tangents.Add(new Vector4(1f, 0f, 0f, -1f));
			uvs.Add(new Vector2((val.x + 1f) * 0.5f, (val.z + 1f) * 0.5f));
		}
	}
}