Decompiled source of RcinelLevel v0.1.0

plugins/RcinelLevel.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("RcinelLevel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+1b2a1c8b0a146554782021c339da76413b01997d")]
[assembly: AssemblyProduct("RcinelLevel")]
[assembly: AssemblyTitle("RcinelLevel")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Rcinel.Level
{
	internal sealed class Controls : IDisposable
	{
		private const float MeasureInterval = 0.5f;

		private const float AimDistance = 60f;

		private const string StoneName = "$item_stone";

		private static readonly int GroundMask = LayerMask.GetMask(new string[1] { "terrain" });

		private static readonly int AnythingMask = LayerMask.GetMask(new string[6] { "terrain", "piece", "piece_nonsolid", "static_solid", "Default", "Default_small" });

		private readonly Settings _settings;

		private readonly ManualLogSource _logger;

		private readonly Frame _frame = new Frame();

		private readonly FrameView _view = new FrameView();

		private readonly Readout _readout = new Readout();

		private readonly ReachOverlay _overlay;

		private Measurement? _measurement;

		private int _measuredRevision = -1;

		private float _measuredAt;

		private (float Fill, int Stone)? _nextStroke;

		private float _plannedAt;

		private Player? _player;

		private ZNet? _session;

		private int _savedRevision = -1;

		public static Controls? Current { get; private set; }

		public Frame Frame => _frame;

		public float? LockedDepth
		{
			get
			{
				if (!_frame.Pinned || !_frame.DepthLocked)
				{
					return null;
				}
				return Target;
			}
		}

		private float? Target => _frame.ManualHeight ?? _frame.PinnedBalance ?? _measurement?.Balance;

		private string TargetSource
		{
			get
			{
				if (!_frame.ManualHeight.HasValue)
				{
					if (!_frame.PinnedBalance.HasValue)
					{
						return "probe";
					}
					return "probe, at pinning";
				}
				return "by hand";
			}
		}

		public Controls(Settings settings, ManualLogSource logger)
		{
			_settings = settings;
			_logger = logger;
			_overlay = new ReachOverlay(logger);
			Current = this;
			settings.Reloaded += ToolHints.Invalidate;
		}

		public void Update()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Invalid comparison between Unknown and I4
			//IL_00f3: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			ScrollPatch.Suppress = false;
			ToolHints.Current = null;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				Hide();
				return;
			}
			KeepFrame(localPlayer);
			bool flag = Items.IsProbe(((Humanoid)localPlayer).GetLeftItem());
			bool flag2 = Items.IsLevelHoe(((Humanoid)localPlayer).GetRightItem());
			int num;
			if (LockedDepth.HasValue)
			{
				ItemData rightItem = ((Humanoid)localPlayer).GetRightItem();
				num = ((rightItem != null && (int)rightItem.m_shared.m_skillType == 12) ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag3 = (byte)num != 0;
			if (!flag && !flag2 && !flag3)
			{
				Hide();
				return;
			}
			_frame.Limit(_settings.MaxRadius.Value);
			MoatSizes.Depth = _settings.MoatDepth.Value;
			if (TakesInput() && (flag || flag2))
			{
				HandleInput(flag);
			}
			if (flag && !_frame.Pinned)
			{
				Vector3? val = Aim(GroundMask);
				if (val.HasValue)
				{
					Vector3 valueOrDefault = val.GetValueOrDefault();
					_frame.MoveTo(valueOrDefault);
				}
			}
			if (_frame.Revision != _measuredRevision || Time.time - _measuredAt > 0.5f)
			{
				Measure();
			}
			if (!_frame.Placed)
			{
				_view.Hide();
				_readout.Show("Hold the ground probe and aim at the ground to frame an area.");
				return;
			}
			(int, int, int, int)? brush = (flag2 ? Brush(localPlayer) : (((int, int, int, int)?)null));
			if (brush.HasValue)
			{
				(int, int, int, int) valueOrDefault2 = brush.GetValueOrDefault();
				float? target = Target;
				if (target.HasValue)
				{
					float valueOrDefault3 = target.GetValueOrDefault();
					if (Time.time - _plannedAt > 0.25f)
					{
						(List<(int, int, int, float)>, float, int, List<(int, int, float)>) tuple = Stroke.Plan(_frame, valueOrDefault2, valueOrDefault3, _settings.StoneCost.Value, _settings.FreeDepth.Value, DevModes.Dig);
						_nextStroke = (tuple.Item2, tuple.Item3);
						_plannedAt = Time.time;
					}
				}
			}
			_view.Show(_frame, Target, brush);
			if (flag)
			{
				Measurement? measurement = _measurement;
				if (measurement.HasValue)
				{
					Measurement valueOrDefault4 = measurement.GetValueOrDefault();
					_overlay.Show(valueOrDefault4);
					goto IL_0265;
				}
			}
			_overlay.Hide();
			goto IL_0265;
			IL_0265:
			_readout.Show(Describe(flag, flag2, flag3, localPlayer));
			ToolHints.Current = ((flag || flag2) ? Hints(flag, flag2) : null);
		}

		private void KeepFrame(Player player)
		{
			World world = ZNet.World;
			if (world == null)
			{
				return;
			}
			if (ZNet.instance != _session)
			{
				_session = ZNet.instance;
				DevModes.Reset();
			}
			string key = $"RcinelLevel.Frame.{world.m_uid}";
			if (player != _player)
			{
				_player = player;
				if (player.m_customData.TryGetValue(key, out var value) && !_frame.Load(value))
				{
					_logger.LogWarning((object)("The saved frame for this world couldn't be read and was dropped: " + value));
				}
				_savedRevision = _frame.Revision;
			}
			else if (_frame.Placed && _frame.Revision != _savedRevision)
			{
				player.m_customData[key] = _frame.Save();
				_savedRevision = _frame.Revision;
			}
		}

		private List<(string[] Keys, string Label)> Hints(bool probe, bool hoe)
		{
			//IL_015d: 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_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			List<(string[], string)> list = new List<(string[], string)>();
			if (hoe)
			{
				list.Add((new string[1] { ZInput.instance.GetBoundKeyString("Attack", false) }, "Fill"));
			}
			if (probe)
			{
				list.Add((new string[1] { KeyName(_settings.CycleShape.Value) }, "Shape"));
				list.Add((new string[1] { KeyName(_settings.PinFrame.Value) }, _frame.Pinned ? "Unpin" : "Pin"));
				list.Add((new string[1] { KeyName(_settings.LockDepth.Value) }, _frame.DepthLocked ? "Unlock pickaxe" : "Lock pickaxe"));
				List<(string[], string)> list2 = list;
				string[] item = new string[1] { KeyName(_settings.CycleMoat.Value) };
				list2.Add((item, "Moat: " + MoatName(_frame.Moat switch
				{
					MoatKind.None => MoatKind.Rustic, 
					MoatKind.Rustic => MoatKind.Drawbridge, 
					_ => MoatKind.None, 
				})));
			}
			list.Add((new string[2]
			{
				KeyName(_settings.ResizeModifier.Value),
				"Wheel"
			}, "Size"));
			list.Add((new string[2]
			{
				KeyName(_settings.HeightModifier.Value),
				"Wheel"
			}, "Height"));
			list.Add((new string[1] { KeyName(_settings.PickHeight.Value) }, "Take height"));
			list.Add((new string[1] { KeyName(_settings.ResetHeight.Value) }, "Probe height"));
			return list;
		}

		private static string MoatName(MoatKind kind)
		{
			return kind switch
			{
				MoatKind.Rustic => Localization.instance.Localize("$piece_drawbridge_log"), 
				MoatKind.Drawbridge => Localization.instance.Localize("$piece_drawbridge"), 
				_ => "none", 
			};
		}

		private unsafe static string KeyName(KeyCode key)
		{
			string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha", StringComparison.Ordinal) && text.Length == 6)
			{
				return text.Substring(5);
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text2 = text;
			foreach (char c in text2)
			{
				if (char.IsUpper(c) && stringBuilder.Length > 0)
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		public void LevelAt(Vector3 point)
		{
			//IL_00b5: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (!_frame.Placed)
			{
				((Character)localPlayer).Message((MessageType)2, "Frame an area with the ground probe first.", 0, (Sprite)null, false);
				return;
			}
			if (!_frame.Pinned)
			{
				Measure();
				_frame.SetPinned(pinned: true, _measurement?.Balance);
				((Character)localPlayer).Message((MessageType)1, "Frame pinned", 0, (Sprite)null, false);
			}
			float? target = Target;
			if (target.HasValue)
			{
				float valueOrDefault = target.GetValueOrDefault();
				(int, int, int, int) tuple = BrushBounds(point);
				if (!Reachable(Mathf.RoundToInt(point.x), Mathf.RoundToInt(point.z)) && TerrainTiles.Cover(tuple, Reachable).Count == 0)
				{
					((Character)localPlayer).Message((MessageType)2, "Aim inside the frame.", 0, (Sprite)null, false);
					return;
				}
				var (list, num, num2, list2) = Stroke.Plan(_frame, tuple, valueOrDefault, _settings.StoneCost.Value, _settings.FreeDepth.Value, DevModes.Dig);
				if (list.Count == 0 && list2.Count == 0)
				{
					if (!DevModes.Dig && HighestUnder(tuple) > valueOrDefault + 0.25f)
					{
						((Character)localPlayer).Message((MessageType)2, "Nothing here lies below the target. Dig with the pickaxe.", 0, (Sprite)null, false);
					}
					return;
				}
				if (num2 > 0 && !localPlayer.NoCostCheat() && !DevModes.NoStone)
				{
					Inventory inventory = ((Humanoid)localPlayer).GetInventory();
					int num3 = inventory.CountItems("$item_stone", -1, true);
					if (num3 < num2)
					{
						((Character)localPlayer).Message((MessageType)2, $"This needs {num2} stone, you have {num3}.", 0, (Sprite)null, false);
						return;
					}
					inventory.RemoveItem("$item_stone", num2, -1, true);
				}
				((MonoBehaviour)RcinelLevelPlugin.Instance).StartCoroutine(TerrainTiles.Level(list, _settings.OpsPerFrame.Value, list2));
				_plannedAt = 0f;
				_logger.LogDebug((object)$"Filling {num:0.0} m³ around ({Mathf.RoundToInt(point.x)}, {Mathf.RoundToInt(point.z)}) to {valueOrDefault:0.00} m for {num2} stone with {list.Count} terrain edits.");
			}
			else
			{
				((Character)localPlayer).Message((MessageType)2, "The ground under the frame isn't loaded yet.", 0, (Sprite)null, false);
			}
			bool Reachable(int x, int z)
			{
				if (!_frame.Contains(x, z))
				{
					if (DevModes.Dig)
					{
						return _frame.InMoat(x, z);
					}
					return false;
				}
				return true;
			}
		}

		public void Dispose()
		{
			Hide();
			if (Current == this)
			{
				Current = null;
			}
		}

		private void Measure()
		{
			_measurement = (_frame.Placed ? Probe.Measure(_frame, Target) : ((Measurement?)null));
			_measuredRevision = _frame.Revision;
			_measuredAt = Time.time;
		}

		private void HandleInput(bool probe)
		{
			//IL_000b: 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_0042: 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)
			//IL_00f7: 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_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: 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)
			bool flag = Keys.Held(_settings.ResizeModifier.Value);
			bool flag2 = Keys.Held(_settings.HeightModifier.Value);
			ScrollPatch.Suppress = flag || flag2;
			if (probe && Keys.Pressed(_settings.CycleShape.Value))
			{
				_frame.CycleShape();
			}
			if (probe && Keys.Pressed(_settings.LockDepth.Value))
			{
				if (!_frame.Pinned && _frame.Placed)
				{
					Measure();
					_frame.SetPinned(pinned: true, _measurement?.Balance);
				}
				_frame.SetDepthLocked(!_frame.DepthLocked);
			}
			if (probe && Keys.Pressed(_settings.CycleMoat.Value))
			{
				_frame.CycleMoat();
			}
			if (probe && Keys.Pressed(_settings.PinFrame.Value))
			{
				if (_frame.Pinned)
				{
					_frame.SetPinned(pinned: false, null);
				}
				else
				{
					Vector3? val = Aim(GroundMask);
					if (val.HasValue)
					{
						Vector3 valueOrDefault = val.GetValueOrDefault();
						_frame.MoveTo(valueOrDefault);
						Measure();
						_frame.SetPinned(pinned: true, _measurement?.Balance);
					}
				}
			}
			float num = (ScrollPatch.Suppress ? ScrollPatch.Read() : 0f);
			if (num != 0f)
			{
				int num2 = ((num > 0f) ? 1 : (-1));
				if (flag)
				{
					_frame.Resize(num2, Facing(), _settings.MaxRadius.Value);
				}
				else
				{
					float? target = Target;
					if (target.HasValue)
					{
						float valueOrDefault2 = target.GetValueOrDefault();
						_frame.SetManualHeight(valueOrDefault2 + (float)num2 * _settings.HeightStep.Value);
					}
				}
			}
			if (Keys.Pressed(_settings.PickHeight.Value))
			{
				Vector3? val = Aim(AnythingMask);
				if (val.HasValue)
				{
					Vector3 valueOrDefault3 = val.GetValueOrDefault();
					_frame.SetManualHeight(valueOrDefault3.y);
				}
			}
			if (Keys.Pressed(_settings.ResetHeight.Value))
			{
				_frame.SetManualHeight(null);
				Measure();
				_frame.Remeasured(_measurement?.Balance);
			}
		}

		private (int MinX, int MinZ, int MaxX, int MaxZ)? Brush(Player player)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = player.m_placementGhost;
			if ((Object)(object)placementGhost != (Object)null && placementGhost.activeSelf)
			{
				return BrushBounds(placementGhost.transform.position);
			}
			Vector3? val = Aim(GroundMask);
			if (val.HasValue)
			{
				Vector3 valueOrDefault = val.GetValueOrDefault();
				return BrushBounds(valueOrDefault);
			}
			return null;
		}

		private float HighestUnder((int MinX, int MinZ, int MaxX, int MaxZ) brush)
		{
			float num = float.MinValue;
			for (int i = brush.MinZ; i <= brush.MaxZ; i++)
			{
				var (j, _, _, _) = brush;
				for (; j <= brush.MaxX; j++)
				{
					if (_frame.Contains(j, i))
					{
						(float, float)? tuple2 = Probe.At(j, i);
						if (tuple2.HasValue)
						{
							num = Math.Max(num, tuple2.GetValueOrDefault().Item1);
						}
					}
				}
			}
			return num;
		}

		private (int MinX, int MinZ, int MaxX, int MaxZ) BrushBounds(Vector3 point)
		{
			//IL_0000: 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)
			int num = Mathf.RoundToInt(point.x);
			int num2 = Mathf.RoundToInt(point.z);
			int value = _settings.HoeBrush.Value;
			return (MinX: num - value, MinZ: num2 - value, MaxX: num + value, MaxZ: num2 + value);
		}

		private string Describe(bool probe, bool hoe, bool pickaxe, Player player)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(probe ? "Ground probe" : (hoe ? "Level hoe" : "Pickaxe")).Append(" · ").Append(_frame.Describe())
				.Append(" · ")
				.Append(_frame.Pinned ? "pinned" : "follows your aim");
			if (_frame.DepthLocked)
			{
				float? target = Target;
				if (target.HasValue)
				{
					float valueOrDefault = target.GetValueOrDefault();
					stringBuilder.Append($" · pickaxe locked at {valueOrDefault:0.00} m");
				}
			}
			if (_frame.Moat != MoatKind.None)
			{
				stringBuilder.Append($" · moat {_frame.MoatWidth} m ({MoatName(_frame.Moat)})");
			}
			if (DevModes.NoStone || DevModes.Dig)
			{
				stringBuilder.Append(" · dev:").Append(DevModes.NoStone ? " no stone" : "").Append(DevModes.Dig ? " dig" : "");
			}
			stringBuilder.AppendLine();
			Measurement? measurement = _measurement;
			Measurement valueOrDefault2;
			if (measurement.HasValue)
			{
				valueOrDefault2 = measurement.GetValueOrDefault();
				float? target = Target;
				if (target.HasValue)
				{
					float valueOrDefault3 = target.GetValueOrDefault();
					stringBuilder.Append($"Target {valueOrDefault3:0.00} m ({TargetSource})").Append($" · dig {valueOrDefault2.Cut:0} m³ · fill {valueOrDefault2.Fill:0} m³");
					if (_frame.Moat != MoatKind.None)
					{
						stringBuilder.AppendLine().Append($"Moat {_frame.MoatWidth} m wide, floor {valueOrDefault3 - MoatSizes.Depth:0.00} m ({MoatSizes.Depth:0.#} m deep): dig {valueOrDefault2.MoatDig:0} m³");
						if (valueOrDefault2.MoatTooDeep > 0)
						{
							stringBuilder.Append($" · {valueOrDefault2.MoatTooDeep} m² can't be dug that deep (red)");
						}
					}
					if (valueOrDefault2.OutOfReach > 0)
					{
						stringBuilder.AppendLine().Append($"Beyond the game's ±{8f:0} m limit (red on the ground):");
						if (valueOrDefault2.TooLow > 0)
						{
							stringBuilder.Append($" {valueOrDefault2.TooLow} m² can't be raised that far");
						}
						if (valueOrDefault2.TooHigh > 0)
						{
							stringBuilder.Append((valueOrDefault2.TooLow > 0) ? "," : string.Empty).Append($" {valueOrDefault2.TooHigh} m² can't be dug that deep");
						}
					}
					if (hoe)
					{
						(float, int)? nextStroke = _nextStroke;
						if (nextStroke.HasValue)
						{
							(float, int) valueOrDefault4 = nextStroke.GetValueOrDefault();
							int num = 2 * _settings.HoeBrush.Value + 1;
							int num2 = ((!DevModes.NoStone && !player.NoCostCheat()) ? valueOrDefault4.Item2 : 0);
							stringBuilder.AppendLine().Append($"Next stroke ({num} × {num} m): fill {valueOrDefault4.Item1:0.0} m³ for {num2} stone").Append(string.Format(" · you carry {0}", ((Humanoid)player).GetInventory().CountItems("$item_stone", -1, true)));
							goto IL_03d8;
						}
					}
					stringBuilder.AppendLine().Append($"Probe now: balance {valueOrDefault2.Balance:0.00} m · ground {valueOrDefault2.Lowest:0.0} to {valueOrDefault2.Highest:0.0} m");
					goto IL_03d8;
				}
			}
			stringBuilder.Append("The ground under the frame isn't loaded yet.");
			goto IL_0424;
			IL_0424:
			return stringBuilder.ToString();
			IL_03d8:
			if (valueOrDefault2.Loaded < valueOrDefault2.Expected)
			{
				stringBuilder.Append($" · only {100 * valueOrDefault2.Loaded / Math.Max(1, valueOrDefault2.Expected)}% of the frame is loaded, the rest is too far away");
			}
			goto IL_0424;
		}

		private void Hide()
		{
			_view.Hide();
			_overlay.Hide();
			_readout.Hide();
		}

		private static Vector3 Facing()
		{
			//IL_001d: 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)
			if (!((Object)(object)GameCamera.instance != (Object)null))
			{
				return Vector3.forward;
			}
			return ((Component)GameCamera.instance).transform.forward;
		}

		private static Vector3? Aim(int mask)
		{
			//IL_001f: 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_002f: 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)
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(new Ray(((Component)instance).transform.position, ((Component)instance).transform.forward), ref val, 60f, mask))
			{
				return null;
			}
			return ((RaycastHit)(ref val)).point;
		}

		private static bool TakesInput()
		{
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible())
			{
				return !Hud.IsPieceSelectionVisible();
			}
			return false;
		}
	}
	internal static class DevModes
	{
		public static bool NoStone { get; set; }

		public static bool Dig { get; set; }

		public static void Reset()
		{
			NoStone = (Dig = false);
		}

		public static void Register()
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new NoStoneCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DigCommand());
		}

		internal static bool Next(bool now, string[] args)
		{
			if (args.Length == 0)
			{
				return !now;
			}
			bool result;
			switch (args[0])
			{
			case "1":
			case "on":
			case "true":
				result = true;
				break;
			default:
				result = false;
				break;
			}
			return result;
		}
	}
	internal abstract class DevCommand : ConsoleCommand
	{
		public override bool IsCheat => true;

		public override List<string> CommandOptionList()
		{
			return new List<string>(2) { "on", "off" };
		}

		public override void Run(string[] args, Terminal context)
		{
			bool flag = Apply(args);
			context.AddString(((ConsoleCommand)this).Name + ": " + (flag ? "on" : "off") + " until you leave the world.");
		}

		protected abstract bool Apply(string[] args);
	}
	internal sealed class NoStoneCommand : DevCommand
	{
		public override string Name => "rcinellevel_nostone";

		public override string Help => "[on|off] The level hoe raises ground without taking stone, for this session.";

		protected override bool Apply(string[] args)
		{
			return DevModes.NoStone = DevModes.Next(DevModes.NoStone, args);
		}
	}
	internal sealed class DigCommand : DevCommand
	{
		public override string Name => "rcinellevel_dig";

		public override string Help => "[on|off] The level hoe also lowers ground above the target, for this session.";

		protected override bool Apply(string[] args)
		{
			return DevModes.Dig = DevModes.Next(DevModes.Dig, args);
		}
	}
	internal enum FrameShape
	{
		Circle,
		Square,
		Rectangle
	}
	internal enum MoatKind
	{
		None,
		Rustic,
		Drawbridge
	}
	internal static class MoatSizes
	{
		public static int RusticWidth { get; set; } = 4;

		public static int DrawbridgeWidth { get; set; } = 8;

		public static float Depth { get; set; } = 3f;

		public static int Width(MoatKind kind)
		{
			return kind switch
			{
				MoatKind.Rustic => RusticWidth, 
				MoatKind.Drawbridge => DrawbridgeWidth, 
				_ => 0, 
			};
		}
	}
	internal sealed class Frame
	{
		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		public FrameShape Shape { get; private set; } = FrameShape.Square;

		public int CenterX { get; private set; }

		public int CenterZ { get; private set; }

		public int Radius { get; private set; } = 4;

		public int North { get; private set; } = 4;

		public int East { get; private set; } = 4;

		public int South { get; private set; } = 4;

		public int West { get; private set; } = 4;

		public bool Placed { get; private set; }

		public bool Pinned { get; private set; }

		public float? PinnedBalance { get; private set; }

		public bool DepthLocked { get; private set; }

		public MoatKind Moat { get; private set; }

		public int MoatWidth => MoatSizes.Width(Moat);

		public (int MinX, int MinZ, int MaxX, int MaxZ) OuterBounds
		{
			get
			{
				(int MinX, int MinZ, int MaxX, int MaxZ) bounds = Bounds;
				int item = bounds.MinX;
				int item2 = bounds.MinZ;
				int item3 = bounds.MaxX;
				int item4 = bounds.MaxZ;
				int moatWidth = MoatWidth;
				return (MinX: item - moatWidth, MinZ: item2 - moatWidth, MaxX: item3 + moatWidth, MaxZ: item4 + moatWidth);
			}
		}

		public float? ManualHeight { get; private set; }

		public int Revision { get; private set; }

		public (int MinX, int MinZ, int MaxX, int MaxZ) Bounds
		{
			get
			{
				if (Shape != FrameShape.Rectangle)
				{
					return (MinX: CenterX - Radius, MinZ: CenterZ - Radius, MaxX: CenterX + Radius, MaxZ: CenterZ + Radius);
				}
				return (MinX: CenterX - West, MinZ: CenterZ - South, MaxX: CenterX + East, MaxZ: CenterZ + North);
			}
		}

		public void CycleMoat()
		{
			Moat = Moat switch
			{
				MoatKind.None => MoatKind.Rustic, 
				MoatKind.Rustic => MoatKind.Drawbridge, 
				_ => MoatKind.None, 
			};
			Revision++;
		}

		public bool InMoat(int x, int z)
		{
			int moatWidth = MoatWidth;
			if (moatWidth == 0 || Contains(x, z))
			{
				return false;
			}
			if (Shape == FrameShape.Circle)
			{
				float num = x - CenterX;
				float num2 = z - CenterZ;
				float num3 = (float)Radius + 0.5f + (float)moatWidth;
				return num * num + num2 * num2 <= num3 * num3;
			}
			var (num4, num5, num6, num7) = OuterBounds;
			if (x >= num4 && x <= num6 && z >= num5)
			{
				return z <= num7;
			}
			return false;
		}

		public void CycleShape()
		{
			Shape = Shape switch
			{
				FrameShape.Circle => FrameShape.Square, 
				FrameShape.Square => FrameShape.Rectangle, 
				_ => FrameShape.Circle, 
			};
			if (Shape == FrameShape.Rectangle)
			{
				int num = (West = Radius);
				int num2 = (South = num);
				int north = (East = num2);
				North = north;
			}
			Revision++;
		}

		public void MoveTo(Vector3 point)
		{
			//IL_0000: 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)
			int num = Mathf.RoundToInt(point.x);
			int num2 = Mathf.RoundToInt(point.z);
			if (!Placed || num != CenterX || num2 != CenterZ)
			{
				CenterX = num;
				CenterZ = num2;
				Placed = true;
				Revision++;
			}
		}

		public void SetPinned(bool pinned, float? balance)
		{
			Pinned = pinned;
			PinnedBalance = (pinned ? balance : ((float?)null));
			DepthLocked &= pinned;
			Revision++;
		}

		public void SetDepthLocked(bool locked)
		{
			DepthLocked = locked && Pinned;
			Revision++;
		}

		public void Remeasured(float? balance)
		{
			if (Pinned)
			{
				PinnedBalance = balance;
			}
			Revision++;
		}

		public void Resize(int step, Vector3 facing, int maxRadius)
		{
			//IL_0023: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (Shape != FrameShape.Rectangle)
			{
				Radius = Mathf.Clamp(Radius + step, 1, maxRadius);
			}
			else if (Mathf.Abs(facing.x) > Mathf.Abs(facing.z))
			{
				if (facing.x > 0f)
				{
					East = Mathf.Clamp(East + step, 0, 2 * maxRadius - West);
				}
				else
				{
					West = Mathf.Clamp(West + step, 0, 2 * maxRadius - East);
				}
			}
			else if (facing.z > 0f)
			{
				North = Mathf.Clamp(North + step, 0, 2 * maxRadius - South);
			}
			else
			{
				South = Mathf.Clamp(South + step, 0, 2 * maxRadius - North);
			}
			Revision++;
		}

		public void Limit(int maxRadius)
		{
			(int, int, int, int, int) valueTuple = (Radius, North, East, South, West);
			Radius = Mathf.Min(Radius, maxRadius);
			North = Mathf.Min(North, 2 * maxRadius);
			South = Mathf.Min(South, 2 * maxRadius - North);
			East = Mathf.Min(East, 2 * maxRadius);
			West = Mathf.Min(West, 2 * maxRadius - East);
			(int, int, int, int, int) tuple = valueTuple;
			int radius = Radius;
			int north = North;
			int east = East;
			int south = South;
			int west = West;
			if (tuple.Item1 != radius || tuple.Item2 != north || tuple.Item3 != east || tuple.Item4 != south || tuple.Item5 != west)
			{
				Revision++;
			}
		}

		public void SetManualHeight(float? height)
		{
			ManualHeight = height;
			Revision++;
		}

		public bool Contains(int x, int z)
		{
			var (num, num2, num3, num4) = Bounds;
			if (x < num || x > num3 || z < num2 || z > num4)
			{
				return false;
			}
			if (Shape != FrameShape.Circle)
			{
				return true;
			}
			float num5 = x - CenterX;
			float num6 = z - CenterZ;
			return num5 * num5 + num6 * num6 <= ((float)Radius + 0.5f) * ((float)Radius + 0.5f);
		}

		public IEnumerable<(int X, int Z)> Vertices()
		{
			(int, int, int, int) bounds = Bounds;
			int minX = bounds.Item1;
			int item = bounds.Item2;
			int maxX = bounds.Item3;
			int maxZ = bounds.Item4;
			for (int z = item; z <= maxZ; z++)
			{
				for (int x = minX; x <= maxX; x++)
				{
					if (Contains(x, z))
					{
						yield return (X: x, Z: z);
					}
				}
			}
		}

		public string Save()
		{
			return string.Join(";", "2", ((int)Shape).ToString(Inv), CenterX.ToString(Inv), CenterZ.ToString(Inv), Radius.ToString(Inv), North.ToString(Inv), East.ToString(Inv), South.ToString(Inv), West.ToString(Inv), Pinned ? "1" : "0", PinnedBalance?.ToString("R", Inv) ?? "", ManualHeight?.ToString("R", Inv) ?? "", DepthLocked ? "1" : "0", ((int)Moat).ToString(Inv));
		}

		public bool Load(string text)
		{
			string[] array = text.Split(new char[1] { ';' });
			if ((array.Length != 13 || !(array[0] == "1")) && (array.Length != 14 || !(array[0] == "2")))
			{
				return false;
			}
			try
			{
				FrameShape frameShape = (FrameShape)int.Parse(array[1], Inv);
				int num = int.Parse(array[2], Inv);
				int num2 = int.Parse(array[3], Inv);
				int num3 = int.Parse(array[4], Inv);
				int num4 = int.Parse(array[5], Inv);
				int num5 = int.Parse(array[6], Inv);
				int num6 = int.Parse(array[7], Inv);
				int num7 = int.Parse(array[8], Inv);
				float? num8 = ((array[10].Length > 0) ? new float?(float.Parse(array[10], Inv)) : ((float?)null));
				float? manualHeight = ((array[11].Length > 0) ? new float?(float.Parse(array[11], Inv)) : ((float?)null));
				FrameShape shape = frameShape;
				int centerX = num;
				int centerZ = num2;
				int radius = num3;
				int north = num4;
				int east = num5;
				int south = num6;
				int west = num7;
				Shape = shape;
				CenterX = centerX;
				CenterZ = centerZ;
				Radius = radius;
				North = north;
				East = east;
				South = south;
				West = west;
				Pinned = array[9] == "1";
				PinnedBalance = (Pinned ? num8 : ((float?)null));
				ManualHeight = manualHeight;
				DepthLocked = Pinned && array[12] == "1";
				Moat = ((array.Length == 14) ? ((MoatKind)int.Parse(array[13], Inv)) : MoatKind.None);
				Placed = true;
				Revision++;
				return true;
			}
			catch (FormatException)
			{
				return false;
			}
		}

		public string Describe()
		{
			var (num, num2, num3, num4) = Bounds;
			return Shape switch
			{
				FrameShape.Circle => $"Circle Ø {2 * Radius + 1} m", 
				FrameShape.Square => $"Square {2 * Radius + 1} × {2 * Radius + 1} m", 
				_ => $"Rectangle {num3 - num + 1} (E–W) × {num4 - num2 + 1} (N–S) m", 
			};
		}
	}
	internal readonly record struct Measurement(float Balance, float Cut, float Fill, int TooLow, int TooHigh, int Loaded, int Expected, float Lowest, float Highest, int MinX, int MinZ, float[,] Heights, IReadOnlyList<(int X, int Z)> Unreachable, float MoatDig, int MoatTooDeep)
	{
		public int OutOfReach => TooLow + TooHigh;
	}
	internal static class Probe
	{
		public const float MaxChange = 8f;

		public static (float Height, float Generated)? At(int x, int z)
		{
			//IL_0010: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor((float)x, 0f, (float)z);
			float num = default(float);
			if (!Heightmap.GetHeight(val, ref num))
			{
				return null;
			}
			TerrainComp val2 = TerrainComp.FindTerrainCompiler(val);
			if (val2 == null || val2.m_levelDelta == null || val2.m_hmap == null)
			{
				return (num, num);
			}
			int num2 = default(int);
			int num3 = default(int);
			val2.m_hmap.WorldToVertex(val, ref num2, ref num3);
			int num4 = val2.m_width + 1;
			if (num2 < 0 || num3 < 0 || num2 >= num4 || num3 >= num4)
			{
				return (num, num);
			}
			int num5 = num3 * num4 + num2;
			return (num, num - val2.m_levelDelta[num5] - val2.m_smoothDelta[num5]);
		}

		public static Measurement? Measure(Frame frame, float? target)
		{
			(int, int, int, int) outerBounds = frame.OuterBounds;
			int minX = outerBounds.Item1;
			int minZ = outerBounds.Item2;
			int maxX = outerBounds.Item3;
			int maxZ = outerBounds.Item4;
			int num = maxX - minX + 1;
			int num2 = maxZ - minZ + 1;
			int num3 = 0;
			for (int i = minZ; i <= maxZ; i++)
			{
				for (int j = minX; j <= maxX; j++)
				{
					if (frame.Contains(j, i) || frame.InMoat(j, i))
					{
						num3++;
					}
				}
			}
			bool[,] seen = new bool[num, num2];
			float[,] grid = new float[num, num2];
			for (int k = 0; k < num2; k++)
			{
				for (int l = 0; l < num; l++)
				{
					grid[l, k] = float.NaN;
				}
			}
			List<(int X, int Z, float Height, float Generated)> heights = new List<(int, int, float, float)>(num3);
			List<(int X, int Z, float Height, float Generated)> moat = new List<(int, int, float, float)>();
			foreach (Heightmap s_heightmap in Heightmap.s_heightmaps)
			{
				Read(s_heightmap);
			}
			if (heights.Count == 0)
			{
				return null;
			}
			double num4 = 0.0;
			float num5 = float.MaxValue;
			float num6 = float.MinValue;
			foreach (var item8 in heights)
			{
				float item = item8.Height;
				num4 += (double)item;
				num5 = Math.Min(num5, item);
				num6 = Math.Max(num6, item);
			}
			float num7 = (float)(num4 / (double)heights.Count);
			float num8 = target ?? num7;
			float num9 = 0f;
			float num10 = 0f;
			int num11 = 0;
			int num12 = 0;
			List<(int, int)> list = new List<(int, int)>();
			foreach (var (item2, item3, num13, num14) in heights)
			{
				if (num13 > num8)
				{
					num9 += num13 - num8;
				}
				else
				{
					num10 += num8 - num13;
				}
				if (num8 - num14 > 8.01f)
				{
					num11++;
					list.Add((item2, item3));
				}
				else if (num14 - num8 > 8.01f)
				{
					num12++;
					list.Add((item2, item3));
				}
			}
			float num15 = 0f;
			int num16 = 0;
			float num17 = num8 - MoatSizes.Depth;
			foreach (var item9 in moat)
			{
				int item4 = item9.X;
				int item5 = item9.Z;
				float item6 = item9.Height;
				float item7 = item9.Generated;
				num15 += Math.Max(0f, item6 - Math.Max(num17, item7 - 8f));
				if (item7 - num17 > 8.01f)
				{
					num16++;
					list.Add((item4, item5));
				}
			}
			return new Measurement(num7, num9, num10, num11, num12, heights.Count + moat.Count, num3, num5, num6, minX, minZ, grid, list, num15, num16);
			void Read(Heightmap heightmap)
			{
				//IL_002f: 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_0047: 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_00b7: 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)
				if (!((Object)(object)heightmap == (Object)null) && heightmap.m_heights.Count != 0 && Mathf.Approximately(heightmap.m_scale, 1f))
				{
					Vector3 position = ((Component)heightmap).transform.position;
					int num18 = heightmap.m_width + 1;
					int num19 = heightmap.m_width / 2;
					int num20 = Mathf.RoundToInt(position.x) - num19;
					int num21 = Mathf.RoundToInt(position.z) - num19;
					int num22 = Math.Max(0, minX - num20);
					int num23 = Math.Min(num18 - 1, maxX - num20);
					int num24 = Math.Max(0, minZ - num21);
					int num25 = Math.Min(num18 - 1, maxZ - num21);
					if (num22 <= num23 && num24 <= num25)
					{
						TerrainComp val = TerrainComp.FindTerrainCompiler(position);
						if ((Object)(object)val != (Object)null && ((Object)(object)val.m_hmap != (Object)(object)heightmap || val.m_levelDelta == null))
						{
							val = null;
						}
						for (int m = num24; m <= num25; m++)
						{
							for (int n = num22; n <= num23; n++)
							{
								int num26 = num20 + n;
								int num27 = num21 + m;
								if (!seen[num26 - minX, num27 - minZ])
								{
									bool flag = frame.Contains(num26, num27);
									if (flag || frame.InMoat(num26, num27))
									{
										seen[num26 - minX, num27 - minZ] = true;
										int num28 = m * num18 + n;
										float num29 = heightmap.m_heights[num28] + position.y;
										float num30 = ((val == null) ? 0f : (val.m_levelDelta[num28] + val.m_smoothDelta[num28]));
										(flag ? heights : moat).Add((num26, num27, num29, num29 - num30));
										grid[num26 - minX, num27 - minZ] = num29;
									}
								}
							}
						}
					}
				}
			}
		}
	}
	internal sealed class FrameView
	{
		private const float Spacing = 1f;

		private const int MaxSegments = 400;

		private static readonly Color TargetTint = new Color(0.45f, 0.85f, 1f, 1f);

		private static readonly Color BrushTint = new Color(1f, 0.55f, 0.2f, 1f);

		private static readonly Color MoatTint = new Color(0.25f, 0.45f, 1f, 1f);

		private readonly List<GameObject> _ground = new List<GameObject>();

		private readonly List<GameObject> _target = new List<GameObject>();

		private readonly List<GameObject> _brush = new List<GameObject>();

		private readonly List<GameObject> _moat = new List<GameObject>();

		private readonly List<(Vector3 Point, Vector3 Tangent)> _outline = new List<(Vector3, Vector3)>();

		private GameObject? _root;

		private int _drawnRevision = -1;

		private float _drawnAt;

		private float? _drawnTarget;

		private (int, int, int, int)? _drawnBrush;

		private static readonly int GroundMask = LayerMask.GetMask(new string[1] { "terrain" });

		public void Show(Frame frame, float? target, (int MinX, int MinZ, int MaxX, int MaxZ)? brush)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null)
			{
				_root = new GameObject("RcinelLevel frame");
				_ground.Clear();
				_target.Clear();
				_brush.Clear();
				_moat.Clear();
				_drawnRevision = -1;
			}
			_root.SetActive(true);
			if (frame.Revision == _drawnRevision && Nullable.Equals(target, _drawnTarget) && Time.time - _drawnAt < 0.5f)
			{
				if (!Nullable.Equals<(int, int, int, int)>(brush, _drawnBrush))
				{
					DrawBrush(frame, target, brush);
				}
				return;
			}
			_drawnRevision = frame.Revision;
			_drawnTarget = target;
			_drawnAt = Time.time;
			Outline(frame);
			RaycastHit val = default(RaycastHit);
			Draw(_ground, null, (Vector3 point) => (!Physics.Raycast(point + Vector3.up * 500f, Vector3.down, ref val, 1000f, GroundMask)) ? ((float?)null) : new float?(((RaycastHit)(ref val)).point.y));
			Draw(_target, TargetTint, (Vector3 _) => target);
			DrawMoat(frame);
			DrawBrush(frame, target, brush);
		}

		private void DrawMoat(Frame frame)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			_outline.Clear();
			if (frame.Moat != MoatKind.None)
			{
				if (frame.Shape == FrameShape.Circle)
				{
					Circle(frame.CenterX, frame.CenterZ, (float)frame.Radius + 0.5f + (float)frame.MoatWidth);
				}
				else
				{
					Rectangle(frame.OuterBounds);
				}
			}
			RaycastHit val = default(RaycastHit);
			Draw(_moat, MoatTint, (Vector3 point) => (!Physics.Raycast(point + Vector3.up * 500f, Vector3.down, ref val, 1000f, GroundMask)) ? ((float?)null) : new float?(((RaycastHit)(ref val)).point.y));
		}

		private void DrawBrush(Frame frame, float? target, (int MinX, int MinZ, int MaxX, int MaxZ)? brush)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			_drawnBrush = brush;
			_outline.Clear();
			if (brush.HasValue)
			{
				(int, int, int, int) valueOrDefault = brush.GetValueOrDefault();
				if (target.HasValue)
				{
					(int MinX, int MinZ, int MaxX, int MaxZ) bounds = frame.Bounds;
					int item = bounds.MinX;
					int item2 = bounds.MinZ;
					int item3 = bounds.MaxX;
					int item4 = bounds.MaxZ;
					(int, int, int, int) bounds2 = (Math.Max(valueOrDefault.Item1, item), Math.Max(valueOrDefault.Item2, item2), Math.Min(valueOrDefault.Item3, item3), Math.Min(valueOrDefault.Item4, item4));
					if (bounds2.Item1 <= bounds2.Item3 && bounds2.Item2 <= bounds2.Item4)
					{
						Rectangle(bounds2);
					}
				}
			}
			Draw(_brush, BrushTint, (Vector3 _) => target);
		}

		public void Hide()
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
		}

		private void Outline(Frame frame)
		{
			_outline.Clear();
			if (frame.Shape == FrameShape.Circle)
			{
				Circle(frame.CenterX, frame.CenterZ, (float)frame.Radius + 0.5f);
			}
			else
			{
				Rectangle(frame.Bounds);
			}
		}

		private void Circle(int centerX, int centerZ, float radius)
		{
			//IL_0056: 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)
			int num = Mathf.Clamp(Mathf.CeilToInt((float)Math.PI * 2f * radius / 1f), 8, 400);
			Vector3 item = default(Vector3);
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)Math.PI * 2f * (float)i / (float)num;
				((Vector3)(ref item))..ctor((float)centerX + Mathf.Sin(num2) * radius, 0f, (float)centerZ + Mathf.Cos(num2) * radius);
				_outline.Add((item, new Vector3(Mathf.Cos(num2), 0f, 0f - Mathf.Sin(num2))));
			}
		}

		private void Rectangle((int MinX, int MinZ, int MaxX, int MaxZ) bounds)
		{
			//IL_007c: 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_00a0: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			(int MinX, int MinZ, int MaxX, int MaxZ) tuple = bounds;
			int item = tuple.MinX;
			int item2 = tuple.MinZ;
			int item3 = tuple.MaxX;
			int item4 = tuple.MaxZ;
			float num = (float)item - 0.5f;
			float num2 = (float)item3 + 0.5f;
			float num3 = (float)item2 - 0.5f;
			float num4 = (float)item4 + 0.5f;
			float spacing = Mathf.Max(1f, 2f * (num2 - num + num4 - num3) / 400f);
			Edge(new Vector3(num, 0f, num3), new Vector3(num2, 0f, num3));
			Edge(new Vector3(num2, 0f, num3), new Vector3(num2, 0f, num4));
			Edge(new Vector3(num2, 0f, num4), new Vector3(num, 0f, num4));
			Edge(new Vector3(num, 0f, num4), new Vector3(num, 0f, num3));
			void Edge(Vector3 from, Vector3 to)
			{
				//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)
				//IL_001c: 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_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_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				float num5 = Vector3.Distance(from, to);
				int num6 = Mathf.Max(1, Mathf.RoundToInt(num5 / spacing));
				Vector3 val = to - from;
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				for (int i = 0; i < num6; i++)
				{
					_outline.Add((Vector3.Lerp(from, to, ((float)i + 0.5f) / (float)num6), normalized));
				}
			}
		}

		private void Draw(List<GameObject> pool, Color? tint, Func<Vector3, float?> height)
		{
			//IL_004c: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//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)
			while (pool.Count < _outline.Count)
			{
				pool.Add(MakeSegment(tint));
			}
			for (int i = 0; i < pool.Count; i++)
			{
				GameObject val = pool[i];
				if (i < _outline.Count)
				{
					float? num = height(_outline[i].Point);
					if (num.HasValue)
					{
						float valueOrDefault = num.GetValueOrDefault();
						var (val2, val3) = _outline[i];
						val.SetActive(true);
						val.transform.SetPositionAndRotation(new Vector3(val2.x, valueOrDefault, val2.z), Quaternion.LookRotation(val3, Vector3.up));
						continue;
					}
				}
				val.SetActive(false);
			}
		}

		private GameObject MakeSegment(Color? tint)
		{
			//IL_0063: 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_00a4: 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)
			GameObject val;
			if ((Object)(object)Items.SegmentPrefab != (Object)null)
			{
				val = Object.Instantiate<GameObject>(Items.SegmentPrefab, _root.transform);
			}
			else
			{
				val = GameObject.CreatePrimitive((PrimitiveType)3);
				Object.Destroy((Object)(object)val.GetComponent<Collider>());
				val.transform.SetParent(_root.transform, false);
				val.transform.localScale = new Vector3(0.05f, 0.05f, 0.6f);
			}
			if (tint.HasValue)
			{
				Color valueOrDefault = tint.GetValueOrDefault();
				Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Material material = componentsInChildren[i].material;
					if (material.HasProperty("_Color"))
					{
						material.color = valueOrDefault;
					}
					if (material.HasProperty("_EmissionColor"))
					{
						material.SetColor("_EmissionColor", valueOrDefault);
					}
				}
			}
			return val;
		}
	}
	internal sealed class Readout
	{
		private static readonly Color Orange = new Color(1f, 0.63f, 0.24f, 1f);

		private Text? _text;

		public void Show(string text)
		{
			if (!((Object)(object)_text == (Object)null) || Create())
			{
				((Component)_text).gameObject.SetActive(true);
				_text.text = text;
			}
		}

		public void Hide()
		{
			if ((Object)(object)_text != (Object)null)
			{
				((Component)_text).gameObject.SetActive(false);
			}
		}

		private bool Create()
		{
			//IL_002b: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			GameObject customGUIFront = GUIManager.CustomGUIFront;
			if ((Object)(object)customGUIFront == (Object)null)
			{
				return false;
			}
			GameObject val = GUIManager.Instance.CreateText(string.Empty, customGUIFront.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -120f), GUIManager.Instance.AveriaSerifBold, 18, Orange, true, Color.black, 1100f, 140f, false);
			_text = val.GetComponent<Text>();
			_text.alignment = (TextAnchor)1;
			_text.supportRichText = true;
			((Graphic)_text).raycastTarget = false;
			return true;
		}
	}
	internal static class Items
	{
		public const string ProbePrefab = "RcinelLevel_Probe";

		public const string HoePrefab = "RcinelLevel_LevelHoe";

		public const string PiecePrefab = "RcinelLevel_Level";

		public const string PieceTableName = "_RcinelLevelHoePieceTable";

		public const string ModelName = "rcinellevel_model";

		private static PluginFiles _files;

		private static Settings _settings;

		private static ManualLogSource _logger;

		private static Mesh? _probeMesh;

		private static Mesh? _hoeMesh;

		private static Texture2D? _atlas;

		private static Sprite? _probeIcon;

		private static Sprite? _hoeIcon;

		public static GameObject? SegmentPrefab { get; private set; }

		public static void Prepare(PluginFiles files, Settings settings, ManualLogSource logger)
		{
			_files = files;
			_settings = settings;
			_logger = logger;
			_probeMesh = files.LoadMesh("probe.obj");
			_hoeMesh = files.LoadMesh("level-hoe.obj");
			_atlas = files.LoadTexture("models", "atlas.png");
			_probeIcon = files.LoadSprite("probe-128.png");
			_hoeIcon = files.LoadSprite("level-hoe-128.png");
			settings.Reloaded += ApplyModelPlacement;
		}

		public static bool IsProbe(ItemData? item)
		{
			return item?.m_shared.m_name == "$item_rcinellevel_probe";
		}

		public static bool IsLevelHoe(ItemData? item)
		{
			return item?.m_shared.m_name == "$item_rcinellevel_levelhoe";
		}

		public static void Create()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Create;
			try
			{
				Material[]? material = MakeMaterials();
				CreateTiles();
				MeasureStoneCost();
				MeasureDrawbridges();
				CreateProbe(material);
				CreatePieceTableAndPiece();
				CreateHoe(material);
				GameObject prefab = PrefabManager.Instance.GetPrefab("piece_workbench");
				SegmentPrefab = ((prefab == null) ? null : prefab.GetComponentInChildren<CircleProjector>(true)?.m_prefab);
				if (SegmentPrefab == null)
				{
					_logger.LogWarning((object)"The workbench's range ring wasn't found, so the frame is drawn without it.");
				}
			}
			catch (Exception arg)
			{
				_logger.LogError((object)$"Creating RcinelLevel's items failed, the tools won't be available: {arg}");
			}
		}

		private static Material[]? MakeMaterials()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b8: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("Hoe");
			Transform obj = ((prefab != null) ? prefab.transform.Find("attach/visual") : null);
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				Transform obj3 = obj.Find("handle");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<MeshRenderer>() : null);
			}
			MeshRenderer val = (MeshRenderer)obj2;
			object obj4;
			if (obj == null)
			{
				obj4 = null;
			}
			else
			{
				Transform obj5 = obj.Find("blade");
				obj4 = ((obj5 != null) ? ((Component)obj5).GetComponent<MeshRenderer>() : null);
			}
			MeshRenderer val2 = (MeshRenderer)obj4;
			if (val == null || val2 == null || _atlas == null)
			{
				_logger.LogWarning((object)"No materials for the models (game hoe or atlas missing); the game's own models stay.");
				return null;
			}
			Material val3 = new Material(((Renderer)val).sharedMaterial)
			{
				name = "rcinellevel_atlas",
				mainTexture = (Texture)(object)_atlas,
				mainTextureScale = Vector2.one,
				mainTextureOffset = Vector2.zero
			};
			string[] array = new string[5] { "_BumpMap", "_MetallicGlossMap", "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
			foreach (string text in array)
			{
				if (val3.HasProperty(text))
				{
					val3.SetTexture(text, (Texture)null);
				}
			}
			if (val3.HasProperty("_Color"))
			{
				val3.color = Color.white;
			}
			return (Material[]?)(object)new Material[2]
			{
				val3,
				((Renderer)val2).sharedMaterial
			};
		}

		private static void CreateTiles()
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: 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_019b: Expected O, but got Unknown
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			GameObject prefab = PrefabManager.Instance.GetPrefab("mud_road_v2");
			TerrainOp val = ((prefab != null) ? prefab.GetComponent<TerrainOp>() : null);
			if (val == null)
			{
				throw new InvalidOperationException("the game's level-ground piece (mud_road_v2) wasn't found");
			}
			Settings settings = val.m_settings;
			_logger.LogInfo((object)$"Game's level ground: level {settings.m_level} r {settings.m_levelRadius} square {settings.m_square} offset {settings.m_levelOffset}, smooth {settings.m_smooth} r {settings.m_smoothRadius}, paint {settings.m_paintCleared} {settings.m_paintType} r {settings.m_paintRadius}");
			int[] radii = TerrainTiles.Radii;
			foreach (int num in radii)
			{
				GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(TerrainTiles.PrefabName(num), ((Component)val).gameObject);
				Object.DestroyImmediate((Object)(object)val2.GetComponent<Piece>());
				foreach (Transform item in val2.transform)
				{
					Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
				}
				TerrainOp component = val2.GetComponent<TerrainOp>();
				Settings settings2 = component.m_settings;
				settings2.m_level = true;
				settings2.m_levelRadius = num;
				settings2.m_square = true;
				settings2.m_levelOffset = 0f;
				settings2.m_raise = false;
				settings2.m_smooth = false;
				settings2.m_paintCleared = false;
				component.m_onPlacedEffect = new EffectList();
				component.m_spawnOnPlaced = null;
				TerrainTiles.Prefabs[num] = component;
			}
			GameObject val3 = PrefabManager.Instance.CreateClonedPrefab("RcinelLevel_Paint", ((Component)val).gameObject);
			Object.DestroyImmediate((Object)(object)val3.GetComponent<Piece>());
			foreach (Transform item2 in val3.transform)
			{
				Object.DestroyImmediate((Object)(object)((Component)item2).gameObject);
			}
			TerrainOp component2 = val3.GetComponent<TerrainOp>();
			Settings settings3 = component2.m_settings;
			settings3.m_level = (settings3.m_raise = (settings3.m_smooth = false));
			settings3.m_paintCleared = true;
			settings3.m_paintType = (PaintType)0;
			settings3.m_paintRadius = 1f;
			settings3.m_paintStrength = 1f;
			settings3.m_paintExp = 0.1f;
			settings3.m_paintCurve = null;
			settings3.m_paintHeightCheck = false;
			settings3.m_addMedianMax = 0f;
			settings3.m_centerMultiplicationFactor = 0f;
			settings3.m_pointMultiplicationFactor = 0f;
			settings3.m_rotation = (settings3.m_sides = false);
			component2.m_onPlacedEffect = new EffectList();
			component2.m_spawnOnPlaced = null;
			TerrainTiles.Paint = component2;
			ObjectDB instance = ObjectDB.instance;
			if (instance != null)
			{
				instance.UpdateRegisters();
			}
		}

		private static void MeasureStoneCost()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("Hoe");
			PieceTable val = ((prefab == null) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces);
			foreach (GameObject item in (val == null) ? new List<GameObject>() : val.m_pieces)
			{
				TerrainOp val2 = (((Object)(object)item == (Object)null) ? null : item.GetComponent<TerrainOp>());
				if (val2 == null || !val2.m_settings.m_raise || val2.m_settings.m_raiseDelta <= 0f)
				{
					continue;
				}
				int num = 0;
				Requirement[] array = item.GetComponent<Piece>()?.m_resources ?? Array.Empty<Requirement>();
				foreach (Requirement val3 in array)
				{
					if ((Object)(object)val3.m_resItem != (Object)null && ((Object)val3.m_resItem).name == "Stone")
					{
						num += val3.m_amount;
					}
				}
				Settings settings = val2.m_settings;
				int num2 = Mathf.CeilToInt(settings.m_raiseRadius);
				float num3 = 0f;
				for (int j = -num2; j <= num2; j++)
				{
					for (int k = -num2; k <= num2; k++)
					{
						float num4 = Mathf.Sqrt((float)(k * k + j * j));
						if (settings.m_square || !(num4 > settings.m_raiseRadius))
						{
							float num5 = ((settings.m_square || settings.m_raisePower <= 0f) ? 1f : Mathf.Pow(1f - num4 / settings.m_raiseRadius, settings.m_raisePower));
							num3 += settings.m_raiseDelta * num5;
						}
					}
				}
				if (num > 0 && num3 > 0f)
				{
					Stroke.StonePerCubicMetre = (float)num / num3;
					_logger.LogInfo((object)$"The game's {((Object)item).name}: {num} stone for {num3:0.00} m³ (radius {settings.m_raiseRadius}, delta {settings.m_raiseDelta}, power {settings.m_raisePower}), so {Stroke.StonePerCubicMetre:0.00} stone per m³.");
					return;
				}
			}
			_logger.LogWarning((object)$"The game's Raise ground wasn't found; the level hoe charges {Stroke.StonePerCubicMetre} stone per m³.");
		}

		private static void MeasureDrawbridges()
		{
			MoatSizes.RusticWidth = Width("piece_drawbridge_log") ?? MoatSizes.RusticWidth;
			MoatSizes.DrawbridgeWidth = Width("piece_drawbridge") ?? MoatSizes.DrawbridgeWidth;
			_logger.LogInfo((object)$"Moat widths: {MoatSizes.RusticWidth} m for the Rustic Drawbridge, {MoatSizes.DrawbridgeWidth} m for the Drawbridge.");
			static int? Width(string name)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: 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_0095: 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)
				GameObject prefab = PrefabManager.Instance.GetPrefab(name);
				Transform val = ((prefab != null) ? prefab.transform.Find("door") : null);
				object obj;
				if (val == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = val.Find("collider");
					obj = ((obj2 != null) ? ((Component)obj2).GetComponent<BoxCollider>() : null);
				}
				BoxCollider val2 = (BoxCollider)obj;
				if (val == null || val2 == null)
				{
					_logger.LogWarning((object)("The deck of " + name + " wasn't found; its moat width stays at the default."));
					return null;
				}
				Transform transform = ((Component)val2).transform;
				float num = val.localPosition.x + transform.localPosition.x + transform.localScale.x * (val2.center.x + val2.size.x / 2f);
				if (!(num > 2.5f))
				{
					return null;
				}
				return Mathf.FloorToInt(num - 1.5f);
			}
		}

		private static void CreateProbe(Material[]? material)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig();
			val.Name = "$item_rcinellevel_probe";
			val.Description = "$item_rcinellevel_probe_description";
			val.CraftingStation = CraftingStations.Workbench;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig("Wood", 2, 0, true),
				new RequirementConfig("Flint", 2, 0, true),
				new RequirementConfig("Resin", 1, 0, true)
			};
			val.Icons = (Sprite[])(object)((_probeIcon == null) ? null : new Sprite[1] { _probeIcon });
			CustomItem val2 = new CustomItem("RcinelLevel_Probe", "Torch", val);
			Transform obj = val2.ItemPrefab.transform.Find("attach");
			Transform val3 = ((obj != null) ? obj.Find("equiped") : null);
			if (val3 != null)
			{
				Object.DestroyImmediate((Object)(object)((Component)val3).gameObject);
			}
			ReplaceModel(obj, (obj != null) ? obj.Find("model") : null, _probeMesh, material, _settings.ProbePosition.Value, _settings.ProbeRotation.Value);
			SharedData shared = val2.ItemDrop.m_itemData.m_shared;
			shared.m_itemType = (ItemType)5;
			shared.m_animationState = (AnimationState)6;
			shared.m_attachOverride = (ItemType)0;
			shared.m_useDurability = false;
			shared.m_durabilityDrain = 0f;
			shared.m_damages = default(DamageTypes);
			shared.m_blockPower = 0f;
			shared.m_deflectionForce = 0f;
			shared.m_timedBlockBonus = 1f;
			shared.m_equipStatusEffect = null;
			shared.m_maxStackSize = 1;
			shared.m_weight = 1f;
			ItemManager.Instance.AddItem(val2);
		}

		private static void CreatePieceTableAndPiece()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			PieceManager.Instance.AddPieceTable(new CustomPieceTable("_RcinelLevelHoePieceTable", new PieceTableConfig
			{
				CanRemovePieces = false
			}));
			CustomPiece val = new CustomPiece("RcinelLevel_Level", "mud_road_v2", new PieceConfig
			{
				Name = "$piece_rcinellevel_level",
				Description = "$piece_rcinellevel_level_description",
				PieceTable = "_RcinelLevelHoePieceTable",
				Icon = _hoeIcon
			});
			Object.DestroyImmediate((Object)(object)val.PiecePrefab.GetComponent<TerrainOp>());
			val.PiecePrefab.AddComponent<LevelAction>();
			val.Piece.m_canRotate = false;
			PieceManager.Instance.AddPiece(val);
		}

		private static void CreateHoe(Material[]? material)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0108: 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)
			ItemConfig val = new ItemConfig();
			val.Name = "$item_rcinellevel_levelhoe";
			val.Description = "$item_rcinellevel_levelhoe_description";
			val.CraftingStation = CraftingStations.Workbench;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig("Hoe", 1, 0, false),
				new RequirementConfig("Flint", 4, 2, true),
				new RequirementConfig("LeatherScraps", 2, 1, true)
			};
			val.Icons = (Sprite[])(object)((_hoeIcon == null) ? null : new Sprite[1] { _hoeIcon });
			CustomItem val2 = new CustomItem("RcinelLevel_LevelHoe", "Hoe", val);
			Transform val3 = val2.ItemPrefab.transform.Find("attach/visual");
			string[] array = new string[2] { "blade", "handle" };
			foreach (string text in array)
			{
				if (val3 != null)
				{
					Transform obj = val3.Find(text);
					if (obj != null)
					{
						((Component)obj).gameObject.SetActive(false);
					}
				}
			}
			ReplaceModel(val3, null, _hoeMesh, material, _settings.HoePosition.Value, _settings.HoeRotation.Value);
			PieceTable pieceTable = PieceManager.Instance.GetPieceTable("_RcinelLevelHoePieceTable");
			SharedData shared = val2.ItemDrop.m_itemData.m_shared;
			shared.m_buildPieces = pieceTable;
			shared.m_maxQuality = 4;
			shared.m_durabilityPerLevel = 50f;
			ItemManager.Instance.AddItem(val2);
		}

		private static void ReplaceModel(Transform? parent, Transform? old, Mesh? mesh, Material[]? material, Vector3 position, Vector3 rotation)
		{
			//IL_004c: 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)
			//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_006b: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			if (parent == null || mesh == null || material == null)
			{
				_logger.LogWarning((object)("Keeping the game's model under " + (((parent != null) ? ((Object)parent).name : null) ?? "(missing)") + ": no mesh or material."));
				return;
			}
			if (old != null)
			{
				((Component)old).gameObject.SetActive(false);
			}
			GameObject val = new GameObject("rcinellevel_model");
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.transform.localEulerAngles = rotation;
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterials = material;
		}

		private static void ApplyModelPlacement()
		{
			//IL_0019: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00fb: 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)
			Place(PrefabManager.Instance.GetPrefab("RcinelLevel_Probe"), _settings.ProbePosition.Value, _settings.ProbeRotation.Value);
			Place(PrefabManager.Instance.GetPrefab("RcinelLevel_LevelHoe"), _settings.HoePosition.Value, _settings.HoeRotation.Value);
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer == null)
			{
				return;
			}
			MeshFilter[] componentsInChildren = ((Component)localPlayer).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!(((Object)val).name != "rcinellevel_model"))
				{
					bool flag = (Object)(object)val.sharedMesh == (Object)(object)_probeMesh;
					((Component)val).transform.localPosition = (flag ? _settings.ProbePosition.Value : _settings.HoePosition.Value);
					((Component)val).transform.localEulerAngles = (flag ? _settings.ProbeRotation.Value : _settings.HoeRotation.Value);
				}
			}
			static void Place(GameObject? prefab, Vector3 position, Vector3 rotation)
			{
				//IL_0032: 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)
				MeshFilter[] array = ((prefab == null) ? Array.Empty<MeshFilter>() : prefab.GetComponentsInChildren<MeshFilter>(true));
				foreach (MeshFilter val2 in array)
				{
					if (((Object)val2).name == "rcinellevel_model")
					{
						((Component)val2).transform.localPosition = position;
						((Component)val2).transform.localEulerAngles = rotation;
					}
				}
			}
		}
	}
	internal static class Keys
	{
		private static readonly Dictionary<KeyCode, KeyControl?> ByLayout = new Dictionary<KeyCode, KeyControl>();

		private static string? _layout;

		public static bool Held(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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)
			if ((int)key != 0)
			{
				KeyControl val = Find(key);
				if (val == null)
				{
					return ZInput.GetKey(key, false);
				}
				return ((ButtonControl)val).isPressed;
			}
			return false;
		}

		public static bool Pressed(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: 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)
			if ((int)key != 0)
			{
				KeyControl val = Find(key);
				if (val == null)
				{
					return ZInput.GetKeyDown(key, false);
				}
				return ((ButtonControl)val).wasPressedThisFrame;
			}
			return false;
		}

		private static KeyControl? Find(KeyCode key)
		{
			//IL_0009: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				string text = Character(key);
				if (text != null)
				{
					if (current.keyboardLayout != _layout)
					{
						_layout = current.keyboardLayout;
						ByLayout.Clear();
					}
					if (!ByLayout.TryGetValue(key, out KeyControl value))
					{
						value = current.FindKeyOnCurrentKeyboardLayout(text);
						ByLayout[key] = value;
					}
					return value;
				}
			}
			return null;
		}

		private static string? Character(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_001a: 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_001e: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key >= 97)
			{
				if ((int)key <= 122)
				{
					return ((char)(97 + (key - 97))).ToString();
				}
			}
			else if ((int)key >= 48 && (int)key <= 57)
			{
				return ((char)(48 + (key - 48))).ToString();
			}
			return null;
		}
	}
	internal static class TerrainTiles
	{
		public static readonly int[] Radii = new int[4] { 4, 2, 1, 0 };

		public static readonly Dictionary<int, TerrainOp> Prefabs = new Dictionary<int, TerrainOp>();

		public const string PaintName = "RcinelLevel_Paint";

		public static TerrainOp? Paint { get; set; }

		public static string PrefabName(int radius)
		{
			return $"RcinelLevel_LevelTile{radius}";
		}

		public static List<(int X, int Z, int Radius)> Cover((int MinX, int MinZ, int MaxX, int MaxZ) bounds, Func<int, int, bool> inside)
		{
			(int MinX, int MinZ, int MaxX, int MaxZ) tuple = bounds;
			int item = tuple.MinX;
			int item2 = tuple.MinZ;
			int item3 = tuple.MaxX;
			int item4 = tuple.MaxZ;
			int num = item3 - item + 1;
			int num2 = item4 - item2 + 1;
			if (num <= 0 || num2 <= 0)
			{
				return new List<(int, int, int)>();
			}
			bool[,] free = new bool[num, num2];
			for (int i = 0; i < num2; i++)
			{
				for (int j = 0; j < num; j++)
				{
					free[j, i] = inside(j + item, i + item2);
				}
			}
			List<(int, int, int)> list = new List<(int, int, int)>();
			int[] radii = Radii;
			foreach (int num3 in radii)
			{
				for (int l = num3; l < num2 - num3; l++)
				{
					for (int m = num3; m < num - num3; m++)
					{
						if (!AllFree(m, l, num3))
						{
							continue;
						}
						list.Add((m + item, l + item2, num3));
						for (int n = -num3; n <= num3; n++)
						{
							for (int num4 = -num3; num4 <= num3; num4++)
							{
								free[m + num4, l + n] = false;
							}
						}
					}
				}
			}
			return list;
			bool AllFree(int gx, int gz, int num6)
			{
				for (int num5 = -num6; num5 <= num6; num5++)
				{
					for (int num7 = -num6; num7 <= num6; num7++)
					{
						if (!free[gx + num7, gz + num5])
						{
							return false;
						}
					}
				}
				return true;
			}
		}

		public static IEnumerator Level(List<(int X, int Z, int Radius, float Height)> tiles, int perFrame, List<(int X, int Z, float Height)>? paint = null)
		{
			int placed = 0;
			foreach (var (num, num2, key, num3) in tiles)
			{
				if (Prefabs.TryGetValue(key, out TerrainOp value))
				{
					Object.Instantiate<GameObject>(((Component)value).gameObject, new Vector3((float)num, num3, (float)num2), Quaternion.identity);
					int num4 = placed + 1;
					placed = num4;
					if (num4 % perFrame == 0)
					{
						yield return null;
					}
				}
			}
			if (paint == null || Paint == null)
			{
				yield break;
			}
			foreach (var (num5, num6, num7) in paint)
			{
				Object.Instantiate<GameObject>(((Component)Paint).gameObject, new Vector3((float)num5, num7, (float)num6), Quaternion.identity);
				int num4 = placed + 1;
				placed = num4;
				if (num4 % perFrame == 0)
				{
					yield return null;
				}
			}
		}

		public static bool IsTile(TerrainOp op)
		{
			if (!((Object)op).name.StartsWith("RcinelLevel_LevelTile", StringComparison.Ordinal))
			{
				return ((Object)op).name.StartsWith("RcinelLevel_Paint", StringComparison.Ordinal);
			}
			return true;
		}
	}
	internal static class Stroke
	{
		public const float NearTarget = 0.25f;

		public static float StonePerCubicMetre { get; set; } = 1f;

		public static (List<(int X, int Z, int Radius, float Height)> Tiles, float Fill, int Stone, List<(int X, int Z, float Height)> Paint) Plan(Frame frame, (int MinX, int MinZ, int MaxX, int MaxZ) brush, float target, float costFactor, float freeDepth, bool dig = false)
		{
			Dictionary<(int, int), float> raise = new Dictionary<(int, int), float>();
			HashSet<(int, int)> lower = new HashSet<(int, int)>();
			List<(int, int, float)> list = new List<(int, int, float)>();
			List<(int, int, float)> list2 = new List<(int, int, float)>();
			for (int i = brush.MinZ; i <= brush.MaxZ; i++)
			{
				var (j, _, _, _) = brush;
				for (; j <= brush.MaxX; j++)
				{
					(float, float)? tuple2;
					if (dig && frame.InMoat(j, i))
					{
						tuple2 = Probe.At(j, i);
						if (tuple2.HasValue)
						{
							(float, float) valueOrDefault = tuple2.GetValueOrDefault();
							float num = Math.Max(target - MoatSizes.Depth, valueOrDefault.Item2 - 8f);
							if (valueOrDefault.Item1 - num > 0.02f)
							{
								list.Add((j, i, num));
								list2.Add((j, i, num));
							}
							continue;
						}
					}
					if (!frame.Contains(j, i))
					{
						continue;
					}
					tuple2 = Probe.At(j, i);
					if (tuple2.HasValue)
					{
						(float, float) valueOrDefault2 = tuple2.GetValueOrDefault();
						float num2 = Math.Min(target, valueOrDefault2.Item2 + 8f);
						if (num2 - valueOrDefault2.Item1 > 0.02f)
						{
							raise[(j, i)] = num2 - valueOrDefault2.Item1;
							list2.Add((j, i, num2));
						}
						else if (dig && valueOrDefault2.Item1 - Math.Max(target, valueOrDefault2.Item2 - 8f) > 0.02f)
						{
							lower.Add((j, i));
							list2.Add((j, i, target));
						}
						else if (valueOrDefault2.Item1 - target <= 0.25f)
						{
							list2.Add((j, i, valueOrDefault2.Item1));
						}
					}
				}
			}
			float num3 = 0f;
			float num4 = 0f;
			foreach (float value in raise.Values)
			{
				num3 += value;
				num4 += Math.Max(0f, value - freeDepth);
			}
			List<(int, int, int, float)> list3 = new List<(int, int, int, float)>();
			foreach (var (item, item2, item3) in TerrainTiles.Cover(brush, (int x, int z) => raise.ContainsKey((x, z)) || lower.Contains((x, z))))
			{
				list3.Add((item, item2, item3, target));
			}
			foreach (var (item4, item5, item6) in list)
			{
				list3.Add((item4, item5, 0, item6));
			}
			return (Tiles: list3, Fill: num3, Stone: Mathf.CeilToInt(num4 * StonePerCubicMetre * costFactor - 0.001f), Paint: list2);
		}
	}
	internal static class DepthLock
	{
		public static bool TakeOver(TerrainOp op)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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)
			//IL_00cc: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			if (!TerrainOp.m_forceDisableTerrainOps && !TerrainTiles.IsTile(op))
			{
				float? num = Controls.Current?.LockedDepth;
				if (num.HasValue)
				{
					float valueOrDefault = num.GetValueOrDefault();
					Settings settings = op.m_settings;
					Player localPlayer = Player.m_localPlayer;
					if (settings.m_raise && !(settings.m_raiseDelta >= 0f) && !settings.m_level && !((Object)(object)localPlayer == (Object)null))
					{
						ItemData rightItem = ((Humanoid)localPlayer).GetRightItem();
						if (rightItem != null && (int)rightItem.m_shared.m_skillType == 12)
						{
							Frame frame = Controls.Current.Frame;
							Vector3 position = ((Component)op).transform.position;
							float raiseRadius = settings.m_raiseRadius;
							int num2 = Mathf.CeilToInt(raiseRadius);
							int num3 = Mathf.RoundToInt(position.x);
							int num4 = Mathf.RoundToInt(position.z);
							bool flag = false;
							for (int i = num4 - num2; i <= num4 + num2; i++)
							{
								if (flag)
								{
									break;
								}
								for (int j = num3 - num2; j <= num3 + num2; j++)
								{
									if (flag)
									{
										break;
									}
									flag = frame.Contains(j, i) || frame.InMoat(j, i);
								}
							}
							if (!flag)
							{
								return false;
							}
							List<(int, int, int, float)> list = new List<(int, int, int, float)>();
							List<(int, int, float)> list2 = new List<(int, int, float)>();
							for (int k = num4 - num2; k <= num4 + num2; k++)
							{
								for (int l = num3 - num2; l <= num3 + num2; l++)
								{
									float num5 = 1f;
									if (!settings.m_square)
									{
										float num6 = Vector2.Distance(new Vector2((float)num3, (float)num4), new Vector2((float)l, (float)k));
										if (num6 > raiseRadius)
										{
											continue;
										}
										if (settings.m_raisePower > 0f)
										{
											num5 = Mathf.Pow(1f - num6 / raiseRadius, settings.m_raisePower);
										}
									}
									bool flag2 = frame.Contains(l, k);
									if (!flag2 && !frame.InMoat(l, k))
									{
										continue;
									}
									(float, float)? tuple = Probe.At(l, k);
									if (tuple.HasValue)
									{
										(float, float) valueOrDefault2 = tuple.GetValueOrDefault();
										float num7 = Math.Max(position.y + settings.m_raiseDelta * num5, flag2 ? valueOrDefault : (valueOrDefault - MoatSizes.Depth));
										if (num7 < valueOrDefault2.Item1 - 0.01f)
										{
											list.Add((l, k, 0, num7));
											list2.Add((l, k, num7));
										}
									}
								}
							}
							((MonoBehaviour)RcinelLevelPlugin.Instance).StartCoroutine(TerrainTiles.Level(list, int.MaxValue, list2));
							op.OnPlaced();
							Object.Destroy((Object)(object)((Component)op).gameObject);
							return true;
						}
					}
					return false;
				}
			}
			return false;
		}
	}
	internal sealed class LevelAction : MonoBehaviour
	{
		private void Awake()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!TerrainOp.m_forceDisableTerrainOps)
			{
				Controls.Current?.LevelAt(((Component)this).transform.position);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class TwoToolsPatch
	{
		private static void Prefix(Humanoid __instance, ItemData item, out (ItemData? Left, ItemData? Right) __state)
		{
			__state = (Left: null, Right: null);
			if (Items.IsLevelHoe(item) && Items.IsProbe(__instance.m_leftItem))
			{
				__state = (Left: __instance.m_leftItem, Right: null);
				__instance.m_leftItem = null;
			}
			else if (Items.IsProbe(item) && Items.IsLevelHoe(__instance.m_rightItem))
			{
				__state = (Left: null, Right: __instance.m_rightItem);
				__instance.m_rightItem = null;
			}
		}

		private static void Postfix(Humanoid __instance, (ItemData? Left, ItemData? Right) __state)
		{
			if (__state.Left != null || __state.Right != null)
			{
				if (__state.Left != null && __instance.m_leftItem == null)
				{
					(__instance.m_leftItem, _) = __state;
				}
				if (__state.Right != null && __instance.m_rightItem == null)
				{
					__instance.m_rightItem = __state.Right;
				}
				__instance.SetupEquipment();
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")]
	internal static class RegisterTilesPatch
	{
		private static void Prefix(ObjectDB __instance)
		{
			foreach (TerrainOp value in TerrainTiles.Prefabs.Values)
			{
				Add(value);
			}
			Add(TerrainTiles.Paint);
			void Add(TerrainOp? op)
			{
				if ((Object)(object)op != (Object)null && !__instance.m_terrainOps.Contains(op))
				{
					__instance.m_terrainOps.Add(op);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
	internal static class ScrollPatch
	{
		private static bool _reading;

		public static bool Suppress { get; set; }

		public static float Read()
		{
			_reading = true;
			try
			{
				return ZInput.GetMouseScrollWheel();
			}
			finally
			{
				_reading = false;
			}
		}

		private static void Postfix(ref float __result)
		{
			if (Suppress && !_reading)
			{
				__result = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(TerrainOp), "Awake")]
	internal static class DepthLockPatch
	{
		private static bool Prefix(TerrainOp __instance)
		{
			return !DepthLock.TakeOver(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
	internal static class NoBuildMenuPatch
	{
		private static bool Prefix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				return !Items.IsLevelHoe(((Humanoid)__instance).GetRightItem());
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateBuild")]
	internal static class NoPieceBoxPatch
	{
		private static GameObject[]? _hidden;

		private static void Postfix(Hud __instance, Player player)
		{
			bool flag = (Object)(object)player == (Object)(object)Player.m_localPlayer && Items.IsLevelHoe(((Humanoid)player).GetRightItem()) && ((Character)player).InPlaceMode();
			GameObject[] array = _hidden ?? (_hidden = Find(__instance));
			foreach (GameObject val in array)
			{
				if ((Object)(object)val != (Object)null && val.activeSelf == flag)
				{
					val.SetActive(!flag);
				}
			}
		}

		private static GameObject[] Find(Hud hud)
		{
			Transform[] array = (Transform[])(object)new Transform[3]
			{
				hud.m_buildSelection.transform,
				hud.m_pieceDescription.transform,
				((Component)hud.m_buildIcon).transform
			};
			Transform val = array[0];
			while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)hud.m_buildHud.transform)
			{
				val = val.parent;
			}
			if ((Object)(object)val.parent == (Object)null || !array[1].IsChildOf(val) || !array[2].IsChildOf(val))
			{
				val = null;
			}
			Transform val2 = (((Object)(object)hud.m_pieceSelectionWindow != (Object)null) ? hud.m_pieceSelectionWindow.transform : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)hud.m_buildHud.transform) && (!((Object)(object)val2 != (Object)null) || !val2.IsChildOf(val)))
			{
				return (GameObject[])(object)new GameObject[1] { ((Component)val).gameObject };
			}
			List<GameObject> list = new List<GameObject>();
			list.Add(((Component)array[0]).gameObject);
			list.Add(((Component)array[1]).gameObject);
			list.Add(((Component)array[2]).gameObject);
			list.AddRange(hud.m_requirementItems);
			return list.ToArray();
		}
	}
	internal sealed class PluginFiles(string directory, ManualLogSource logger)
	{
		public Mesh? LoadMesh(string name)
		{
			return Load(Path.Combine(directory, "models", name), (string path) => ObjMesh.Read(path, Path.GetFileNameWithoutExtension(path)));
		}

		public Texture2D? LoadTexture(string folder, string name)
		{
			return Load(Path.Combine(directory, folder, name), (Func<string, Texture2D>)delegate(string path)
			{
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true)
				{
					name = Path.GetFileNameWithoutExtension(path)
				};
				if (!AssetUtils.LoadImage(val, File.ReadAllBytes(path)))
				{
					throw new InvalidDataException("not a PNG Unity can read");
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				return val;
			});
		}

		public Sprite? LoadSprite(string name)
		{
			//IL_0029: 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)
			Texture2D val = LoadTexture("icons", name);
			if (val != null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			}
			return null;
		}

		private T? Load<T>(string path, Func<string, T> read) where T : class
		{
			try
			{
				return read(path);
			}
			catch (Exception ex)
			{
				logger.LogError((object)("Couldn't load " + path + ": " + ex.Message));
				return null;
			}
		}
	}
	internal static class ObjMesh
	{
		public static Mesh Read(string path, string name)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> positions = new List<Vector3>();
			List<Vector2> uvs = new List<Vector2>();
			List<Vector3> normals = new List<Vector3>();
			Dictionary<(int, int, int), int> corners = new Dictionary<(int, int, int), int>();
			List<Vector3> vertices = new List<Vector3>();
			List<Vector2> vertexUvs = new List<Vector2>();
			List<Vector3> vertexNormals = new List<Vector3>();
			List<int>[] array = new List<int>[2]
			{
				new List<int>(),
				new List<int>()
			};
			int num = 0;
			foreach (string item in File.ReadLines(path))
			{
				string[] array2 = item.Trim().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
				if (array2.Length == 0)
				{
					continue;
				}
				switch (array2[0])
				{
				case "v":
					positions.Add(new Vector3(0f - Float(array2[1]), Float(array2[2]), Float(array2[3])));
					break;
				case "vt":
					uvs.Add(new Vector2(Float(array2[1]), Float(array2[2])));
					break;
				case "vn":
					normals.Add(new Vector3(0f - Float(array2[1]), Float(array2[2]), Float(array2[3])));
					break;
				case "usemtl":
					num = ((array2.Length > 1 && array2[1] == "stone") ? 1 : 0);
					break;
				case "f":
					if (array2.Length != 4)
					{
						throw new InvalidDataException($"only triangles are read, but a face has {array2.Length - 1} corners");
					}
					array[num].Add(Corner(array2[1]));
					array[num].Add(Corner(array2[3]));
					array[num].Add(Corner(array2[2]));
					break;
				}
			}
			if (array[0].Count + array[1].Count == 0)
			{
				throw new InvalidDataException("no faces");
			}
			Mesh val = new Mesh
			{
				name = name,
				subMeshCount = 2
			};
			val.SetVertices(vertices);
			val.SetUVs(0, vertexUvs);
			val.SetNormals(vertexNormals);
			val.SetTriangles(array[0], 0);
			val.SetTriangles(array[1], 1);
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
			int Corner(string text)
			{
				//IL_006c: 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_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				string[] ids = text.Split(new char[1] { '/' });
				(int, int, int) key = (Index(ids, 0), Index(ids, 1), Index(ids, 2));
				if (!corners.TryGetValue(key, out var value))
				{
					value = vertices.Count;
					corners[key] = value;
					vertices.Add(positions[key.Item1]);
					vertexUvs.Add((key.Item2 >= 0) ? uvs[key.Item2] : Vector2.zero);
					vertexNormals.Add((key.Item3 >= 0) ? normals[key.Item3] : Vector3.up);
				}
				return value;
			}
		}

		private static int Index(string[] ids, int slot)
		{
			if (slot >= ids.Length || ids[slot].Length <= 0)
			{
				return -1;
			}
			return int.Parse(ids[slot], CultureInfo.InvariantCulture) - 1;
		}

		private static float Float(string text)
		{
			return float.Parse(text, NumberStyles.Float, CultureInfo.InvariantCulture);
		}
	}
	[BepInPlugin("io.github.codeisnotevil.rcinellevel", "RcinelLevel", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class RcinelLevelPlugin : BaseUnityPlugin
	{
		public const string Guid = "io.github.codeisnotevil.rcinellevel";

		public const string Name = "RcinelLevel";

		public const string Version = "0.1.0";

		private Controls? _controls;

		internal static RcinelLevelPlugin Instance { get; private set; }

		internal Settings Settings { get; private set; }

		private void Awake()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Settings = new Settings(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			PluginFiles files = new PluginFiles(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), ((BaseUnityPlugin)this).Logger);
			Texts.Register();
			DevModes.Register();
			Items.Prepare(files, Settings, ((BaseUnityPlugin)this).Logger);
			PrefabManager.OnVanillaPrefabsAvailable += Items.Create;
			new Harmony("io.github.codeisnotevil.rcinellevel").PatchAll(typeof(RcinelLevelPlugin).Assembly);
			_controls = new Controls(Settings, ((BaseUnityPlugin)this).Logger);
			Game.isModded = true;
		}

		private void Update()
		{
			Settings.ReloadIfChanged();
			_controls?.Update();
		}

		private void OnDestroy()
		{
			_controls?.Dispose();
			Settings.Dispose();
		}
	}
	internal sealed class ReachOverlay(ManualLogSource logger)
	{
		private const float Lift = 0.08f;

		private static readonly Color Warning = new Color(0.9f, 0.12f, 0.06f, 0.38f);

		private GameObject? _root;

		private Mesh? _mesh;

		private bool _noShader;

		private Measurement? _shown;

		public void Show(Measurement measurement)
		{
			if (measurement.Unreachable.Count == 0)
			{
				Hide();
			}
			else if (Ready())
			{
				_root.SetActive(true);
				Measurement? shown = _shown;
				if (!shown.HasValue || shown.GetValueOrDefault().Unreachable != measurement.Unreachable)
				{
					_shown = measurement;
					Build(measurement);
				}
			}
		}

		public void Hide()
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
		}

		private bool Ready()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			if ((Object)(object)_root != (Object)null)
			{
				return true;
			}
			if (_noShader)
			{
				return false;
			}
			Shader val = null;
			string[] array = new string[3] { "Sprites/Default", "UI/Default", "Hidden/Internal-Colored" };
			for (int i = 0; i < array.Length; i++)
			{
				val = Shader.Find(array[i]);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				_noShader = true;
				logger.LogWarning((object)"No transparent built-in shader was found, so the probe shows no red overlay.");
				return false;
			}
			_root = new GameObject("RcinelLevel reach overlay");
			_mesh = new Mesh
			{
				name = "rcinellevel_reach",
				indexFormat = (IndexFormat)1
			};
			_mesh.MarkDynamic();
			_root.AddComponent<MeshFilter>().sharedMesh = _mesh;
			MeshRender