Decompiled source of FlatHoe v1.0.0

plugins/FlatHoe/FlatHoe.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FlatHoe
{
	internal class FlatPreview : MonoBehaviour
	{
		private const int CircleSegments = 48;

		private const int SquareSegments = 40;

		private const float PlaneLift = 0.06f;

		private static readonly Color FillColor = new Color(0.15f, 1f, 0.28f, 0.22f);

		private static readonly Color LineColor = new Color(0.25f, 1f, 0.35f, 0.95f);

		private static readonly Color DepthColor = new Color(0.2f, 0.95f, 0.3f, 0.4f);

		private static Material _fillMat;

		private static Material _lineMat;

		private static Material _depthMat;

		private static bool _loggedShader;

		private MeshFilter _fillFilter;

		private MeshRenderer _fillRenderer;

		private Mesh _fillMesh;

		private MeshFilter _depthFilter;

		private MeshRenderer _depthRenderer;

		private Mesh _depthMesh;

		private LineRenderer _border;

		private LineRenderer _groundBorder;

		public static float LastDepth { get; private set; }

		public static float Width => Plugin.CurrentRadius * 2f;

		public static void Attach(GameObject ghost)
		{
			if (!((Object)(object)ghost == (Object)null))
			{
				FlatPreview obj = ghost.GetComponent<FlatPreview>() ?? ghost.AddComponent<FlatPreview>();
				obj.Ensure();
				obj.Refresh();
			}
		}

		private void Ensure()
		{
			//IL_0042: 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_0057: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			EnsureMaterials();
			if ((Object)(object)_fillFilter == (Object)null)
			{
				Transform val = Child("FlatPreviewFill");
				_fillFilter = ((Component)val).gameObject.AddComponent<MeshFilter>();
				_fillRenderer = ((Component)val).gameObject.AddComponent<MeshRenderer>();
				_fillMesh = new Mesh
				{
					name = "FlatPreviewFill"
				};
				_fillFilter.sharedMesh = _fillMesh;
				SetupRenderer(_fillRenderer, _fillMat);
			}
			if ((Object)(object)_depthFilter == (Object)null)
			{
				Transform val2 = Child("FlatPreviewDepth");
				_depthFilter = ((Component)val2).gameObject.AddComponent<MeshFilter>();
				_depthRenderer = ((Component)val2).gameObject.AddComponent<MeshRenderer>();
				_depthMesh = new Mesh
				{
					name = "FlatPreviewDepth"
				};
				_depthFilter.sharedMesh = _depthMesh;
				SetupRenderer(_depthRenderer, _depthMat);
			}
			if ((Object)(object)_border == (Object)null)
			{
				_border = MakeLine("FlatPreviewBorder", LineColor, 0.08f);
			}
			if ((Object)(object)_groundBorder == (Object)null)
			{
				_groundBorder = MakeLine("FlatPreviewGround", LineColor, 0.05f);
			}
		}

		public void Refresh()
		{
			//IL_0049: 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_004e: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_fillMesh == (Object)null)
			{
				Ensure();
			}
			CircleProjector[] componentsInChildren = ((Component)this).GetComponentsInChildren<CircleProjector>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
			}
			Quaternion val = (Plugin.UseSquare ? Plugin.PlayerFlatRotation() : Quaternion.identity);
			AlignFacing(((Component)_fillFilter).transform, val);
			AlignFacing(((Component)_depthFilter).transform, val);
			AlignFacing(((Component)_border).transform, val);
			AlignFacing(((Component)_groundBorder).transform, val);
			float currentRadius = Plugin.CurrentRadius;
			bool useSquare = Plugin.UseSquare;
			int num = (useSquare ? 40 : 48);
			Vector3 position = ((Component)this).transform.position;
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			float num2 = 0f;
			for (int j = 0; j < num; j++)
			{
				Vector3 val2 = PerimeterPoint(useSquare, currentRadius, j, num);
				float num3 = GroundY(position + val * val2);
				array[j] = new Vector3(val2.x, 0.06f, val2.z);
				array2[j] = new Vector3(val2.x, num3 - position.y, val2.z);
				num2 = Mathf.Max(num2, Mathf.Abs(num3 - position.y));
			}
			LastDepth = num2;
			BuildFill(array);
			BuildSkirt(array, array2);
			SetLoop(_border, array);
			SetLoop(_groundBorder, array2);
			RestoreColors();
		}

		private void BuildFill(Vector3[] ring)
		{
			//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_0032: 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)
			int num = ring.Length;
			Vector3[] array = (Vector3[])(object)new Vector3[num + 1];
			array[0] = new Vector3(0f, 0.06f, 0f);
			for (int i = 0; i < num; i++)
			{
				array[i + 1] = ring[i];
			}
			int[] array2 = new int[num * 3];
			for (int j = 0; j < num; j++)
			{
				int num2 = j * 3;
				array2[num2] = 0;
				array2[num2 + 1] = j + 1;
				array2[num2 + 2] = ((j + 2 > num) ? 1 : (j + 2));
			}
			_fillMesh.Clear();
			_fillMesh.vertices = array;
			_fillMesh.triangles = array2;
			_fillMesh.RecalculateNormals();
			_fillMesh.RecalculateBounds();
		}

		private void BuildSkirt(Vector3[] top, Vector3[] bottom)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			int num = top.Length;
			Vector3[] array = (Vector3[])(object)new Vector3[num * 2];
			int[] array2 = new int[num * 6];
			for (int i = 0; i < num; i++)
			{
				array[i] = top[i];
				array[num + i] = bottom[i];
			}
			for (int j = 0; j < num; j++)
			{
				int num2 = (j + 1) % num;
				int num3 = j * 6;
				array2[num3] = j;
				array2[num3 + 1] = num2;
				array2[num3 + 2] = num + j;
				array2[num3 + 3] = num2;
				array2[num3 + 4] = num + num2;
				array2[num3 + 5] = num + j;
			}
			_depthMesh.Clear();
			_depthMesh.vertices = array;
			_depthMesh.triangles = array2;
			_depthMesh.RecalculateNormals();
			_depthMesh.RecalculateBounds();
		}

		private static void SetLoop(LineRenderer line, Vector3[] points)
		{
			line.loop = true;
			line.positionCount = points.Length;
			line.SetPositions(points);
		}

		private static Vector3 PerimeterPoint(bool square, float radius, int i, int count)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (!square)
			{
				float num = (float)Math.PI * 2f * (float)i / (float)count;
				return new Vector3(Mathf.Sin(num) * radius, 0f, Mathf.Cos(num) * radius);
			}
			float num2 = radius * 2f;
			float num3 = num2 * 4f * (float)i / (float)count;
			if (num3 < num2)
			{
				return new Vector3(0f - radius + num3, 0f, 0f - radius);
			}
			num3 -= num2;
			if (num3 < num2)
			{
				return new Vector3(radius, 0f, 0f - radius + num3);
			}
			num3 -= num2;
			if (num3 < num2)
			{
				return new Vector3(radius - num3, 0f, radius);
			}
			num3 -= num2;
			return new Vector3(0f - radius, 0f, radius - num3);
		}

		private static float GroundY(Vector3 world)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				return ZoneSystem.instance.GetGroundHeight(world);
			}
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(world + Vector3.up * 80f, Vector3.down, ref val, 200f))
			{
				return ((RaycastHit)(ref val)).point.y;
			}
			return world.y;
		}

		private static void AlignFacing(Transform t, Quaternion facing)
		{
			//IL_000b: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)t == (Object)null))
			{
				t.rotation = facing;
				t.position = (((Object)(object)t.parent != (Object)null) ? t.parent.position : t.position);
				t.localScale = Vector3.one;
			}
		}

		private Transform Child(string name)
		{
			//IL_0019: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = new GameObject(name);
			val2.transform.SetParent(((Component)this).transform, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.layer = ((Component)this).gameObject.layer;
			return val2.transform;
		}

		private LineRenderer MakeLine(string name, Color color, float width)
		{
			//IL_004e: 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)
			LineRenderer obj = ((Component)Child(name)).gameObject.AddComponent<LineRenderer>();
			((Renderer)obj).sharedMaterial = _lineMat;
			obj.useWorldSpace = false;
			obj.loop = true;
			obj.widthMultiplier = width;
			obj.numCapVertices = 2;
			obj.numCornerVertices = 2;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			obj.startColor = color;
			obj.endColor = color;
			obj.textureMode = (LineTextureMode)0;
			return obj;
		}

		private static void SetupRenderer(MeshRenderer renderer, Material material)
		{
			((Renderer)renderer).sharedMaterial = material;
			((Renderer)renderer).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)renderer).receiveShadows = false;
			((Renderer)renderer).lightProbeUsage = (LightProbeUsage)0;
			((Renderer)renderer).reflectionProbeUsage = (ReflectionProbeUsage)0;
		}

		private void RestoreColors()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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)
			if ((Object)(object)_fillRenderer != (Object)null)
			{
				((Renderer)_fillRenderer).sharedMaterial = _fillMat;
			}
			if ((Object)(object)_depthRenderer != (Object)null)
			{
				((Renderer)_depthRenderer).sharedMaterial = _depthMat;
			}
			if ((Object)(object)_border != (Object)null)
			{
				((Renderer)_border).sharedMaterial = _lineMat;
				_border.startColor = LineColor;
				_border.endColor = LineColor;
			}
			if ((Object)(object)_groundBorder != (Object)null)
			{
				((Renderer)_groundBorder).sharedMaterial = _lineMat;
				_groundBorder.startColor = LineColor;
				_groundBorder.endColor = LineColor;
			}
		}

		private static void EnsureMaterials()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_00a6: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_fillMat != (Object)null)
			{
				return;
			}
			Shader obj = FindShader();
			_fillMat = new Material(obj)
			{
				color = FillColor
			};
			_depthMat = new Material(obj)
			{
				color = DepthColor
			};
			_lineMat = new Material(obj)
			{
				color = LineColor
			};
			Material[] array = (Material[])(object)new Material[3] { _fillMat, _depthMat, _lineMat };
			foreach (Material val in array)
			{
				val.SetInt("_ZWrite", 0);
				val.renderQueue = 3000;
				if (val.HasProperty("_Color"))
				{
					val.SetColor("_Color", val.color);
				}
				if (val.HasProperty("_BaseColor"))
				{
					val.SetColor("_BaseColor", val.color);
				}
				if (val.HasProperty("_TintColor"))
				{
					val.SetColor("_TintColor", val.color);
				}
			}
		}

		private static Shader FindShader()
		{
			string[] array = new string[8] { "Sprites/Default", "Legacy Shaders/Particles/Alpha Blended", "Particles/Standard Unlit", "Unlit/Color", "Legacy Shaders/Transparent/Diffuse", "UI/Default", "Universal Render Pipeline/Unlit", "Hidden/Internal-Colored" };
			foreach (string text in array)
			{
				Shader val = Shader.Find(text);
				if (!((Object)(object)val == (Object)null))
				{
					if (!_loggedShader)
					{
						_loggedShader = true;
						Plugin.LogInfo("Preview shader: " + text);
					}
					return val;
				}
			}
			return Shader.Find("Standard") ?? Shader.Find("Diffuse");
		}
	}
	internal static class HoeFlatPieces
	{
		private static GameObject _dirt;

		private static GameObject _paved;

		private static float _nextAttempt;

		public static bool IsRegistered
		{
			get
			{
				if ((Object)(object)_dirt != (Object)null)
				{
					return (Object)(object)_paved != (Object)null;
				}
				return false;
			}
		}

		public static void TryRegister()
		{
			if (IsRegistered || Time.time < _nextAttempt)
			{
				return;
			}
			_nextAttempt = Time.time + 1.5f;
			try
			{
				Register();
			}
			catch (Exception arg)
			{
				Plugin.LogError($"Flat Hoe register failed: {arg}");
			}
		}

		public static void Unregister()
		{
			try
			{
				PieceTable val = FindHoeTable();
				if (val?.m_pieces != null)
				{
					val.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null || Plugin.IsOurPrefab(p));
				}
				UnregisterTerrainOp(_dirt);
				UnregisterTerrainOp(_paved);
			}
			catch (Exception arg)
			{
				Plugin.LogError($"Flat Hoe unregister failed: {arg}");
			}
			_dirt = null;
			_paved = null;
			_nextAttempt = 0f;
		}

		public static void RegisterTerrainOps()
		{
			RegisterTerrainOp(_dirt);
			RegisterTerrainOp(_paved);
		}

		public static void ApplyRadiusToRegistered()
		{
			ApplySettings(_dirt);
			ApplySettings(_paved);
		}

		public static bool IsLocalToolActive()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode())
			{
				return false;
			}
			GameObject placementGhost = Plugin.GetPlacementGhost(localPlayer);
			if ((Object)(object)placementGhost != (Object)null && Plugin.IsOurPrefab(placementGhost))
			{
				return true;
			}
			PieceTable buildPieces = Plugin.GetBuildPieces(localPlayer);
			Piece val = (((Object)(object)buildPieces != (Object)null) ? buildPieces.GetSelectedPiece() : null);
			if ((Object)(object)val != (Object)null)
			{
				return Plugin.IsOurPrefab(((Component)val).gameObject);
			}
			return false;
		}

		public static void ApplyToGhost(GameObject ghost)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.IsOurPrefab(ghost))
			{
				return;
			}
			ApplySettings(ghost);
			if (Player.IsPlacementGhost(ghost) && Plugin.UseSquare)
			{
				Vector3 position = ghost.transform.position;
				ghost.transform.rotation = Plugin.PlayerFlatRotation();
				ghost.transform.position = position;
			}
			CircleProjector[] componentsInChildren = ghost.GetComponentsInChildren<CircleProjector>(true);
			foreach (CircleProjector val in componentsInChildren)
			{
				val.m_radius = Plugin.CurrentRadius;
				if (Player.IsPlacementGhost(ghost))
				{
					((Behaviour)val).enabled = false;
				}
			}
			if (Player.IsPlacementGhost(ghost))
			{
				FlatPreview.Attach(ghost);
			}
		}

		private static void Register()
		{
			ZNetScene instance = ZNetScene.instance;
			ObjectDB instance2 = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null)
			{
				return;
			}
			PieceTable val = FindHoeTable();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.LogWarning("Hoe piece table not found.");
				return;
			}
			val.m_pieces.RemoveAll((GameObject p) => (Object)(object)p == (Object)null);
			if (val.m_pieces.Exists((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name == "FlatHoe_Dirt"))
			{
				_dirt = val.m_pieces.Find((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name == "FlatHoe_Dirt");
				_paved = val.m_pieces.Find((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name == "FlatHoe_Paved");
				RegisterTerrainOps();
				return;
			}
			GameObject val2 = FindSource(val, instance, "mud_road_v2", "mud_road") ?? FindPaintSource(val, (PaintType)0);
			GameObject val3 = FindSource(val, instance, "paved_road_v2", "paved_road") ?? FindPaintSource(val, (PaintType)2);
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = FindAnyTerrainPiece(val);
			}
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val2;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.LogWarning("No hoe TerrainOp piece to clone.");
				return;
			}
			_dirt = ClonePiece(instance, val, val2, "FlatHoe_Dirt", "$flathoe_dirt", "$flathoe_dirt_desc", (PaintType)0);
			_paved = ClonePiece(instance, val, val3, "FlatHoe_Paved", "$flathoe_paved", "$flathoe_paved_desc", (PaintType)2);
			Loc.Apply();
			RefreshPlayerPieces();
		}

		private static GameObject ClonePiece(ZNetScene scene, PieceTable hoe, GameObject source, string cloneName, string nameToken, string descToken, PaintType paint)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			TerrainOp.m_forceDisableTerrainOps = true;
			ZNetView.m_forceDisableInit = true;
			GameObject val;
			try
			{
				val = Object.Instantiate<GameObject>(source, ((Component)scene).transform);
			}
			finally
			{
				TerrainOp.m_forceDisableTerrainOps = false;
				ZNetView.m_forceDisableInit = false;
			}
			((Object)val).name = cloneName;
			val.transform.localPosition = new Vector3(0f, -10000f, 0f);
			TerrainOp val2 = val.GetComponent<TerrainOp>() ?? val.GetComponentInChildren<TerrainOp>(true);
			if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)(object)val)
			{
				((Object)((Component)val2).gameObject).name = cloneName;
			}
			Piece component = val.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = nameToken;
				component.m_description = descToken;
				component.m_enabled = true;
				component.m_canRotate = false;
				component.m_groundPiece = true;
				component.m_groundOnly = true;
				if (!Plugin.RequireResources.Value)
				{
					component.m_resources = Array.Empty<Requirement>();
				}
			}
			ApplySettings(val, paint);
			RegisterInScene(scene, val);
			RegisterTerrainOp(val);
			if (!hoe.m_pieces.Contains(val))
			{
				hoe.m_pieces.Add(val);
			}
			Plugin.LogInfo("Added hoe piece '" + cloneName + "' from '" + ((Object)source).name + "'.");
			return val;
		}

		private static void ApplySettings(GameObject go, PaintType? paint = null)
		{
			//IL_00b6: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)go == (Object)null))
			{
				TerrainOp val = go.GetComponent<TerrainOp>() ?? go.GetComponentInChildren<TerrainOp>(true);
				if (!((Object)(object)val == (Object)null))
				{
					Settings settings = val.m_settings;
					settings.m_level = true;
					settings.m_raise = false;
					settings.m_smooth = Plugin.SmoothEdges.Value;
					settings.m_square = Plugin.UseSquare;
					settings.m_rotation = Plugin.UseSquare;
					settings.m_halfOffset = false;
					settings.m_levelOffset = 0f;
					settings.m_levelRadius = Plugin.CurrentRadius;
					settings.m_paintRadius = Plugin.CurrentRadius;
					settings.m_smoothRadius = Plugin.CurrentRadius;
					settings.m_paintCleared = true;
					settings.m_paintHeightCheck = false;
					settings.m_paintType = (PaintType)(((??)paint) ?? Plugin.PaintFor(go));
				}
			}
		}

		private static void RegisterInScene(ZNetScene scene, GameObject prefab)
		{
			if (!scene.m_prefabs.Contains(prefab))
			{
				scene.m_prefabs.Add(prefab);
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			Dictionary<int, GameObject> value = Traverse.Create((object)scene).Field<Dictionary<int, GameObject>>("m_namedPrefabs").Value;
			if (value != null)
			{
				value[stableHashCode] = prefab;
			}
		}

		private static void RegisterTerrainOp(GameObject go)
		{
			if ((Object)(object)go == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			TerrainOp val = go.GetComponent<TerrainOp>() ?? go.GetComponentInChildren<TerrainOp>(true);
			if (!((Object)(object)val == (Object)null))
			{
				ObjectDB instance = ObjectDB.instance;
				if (!instance.m_terrainOps.Contains(val))
				{
					instance.m_terrainOps.Add(val);
				}
				instance.m_terrainOpsByHash[instance.GetPrefabHash(((Component)val).gameObject)] = val;
			}
		}

		private static void UnregisterTerrainOp(GameObject go)
		{
			if (!((Object)(object)go == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				TerrainOp val = go.GetComponent<TerrainOp>() ?? go.GetComponentInChildren<TerrainOp>(true);
				if (!((Object)(object)val == (Object)null))
				{
					ObjectDB instance = ObjectDB.instance;
					instance.m_terrainOps.Remove(val);
					instance.m_terrainOpsByHash.Remove(instance.GetPrefabHash(((Component)val).gameObject));
				}
			}
		}

		private static PieceTable FindHoeTable()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hoe");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return null;
			}
			return itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
		}

		private static GameObject FindSource(PieceTable hoe, ZNetScene scene, params string[] names)
		{
			foreach (string text in names)
			{
				foreach (GameObject piece in hoe.m_pieces)
				{
					if ((Object)(object)piece != (Object)null && Utils.GetPrefabName(((Object)piece).name) == text)
					{
						return piece;
					}
				}
				GameObject prefab = scene.GetPrefab(text);
				if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TerrainOp>() != (Object)null)
				{
					return prefab;
				}
			}
			return null;
		}

		private static GameObject FindPaintSource(PieceTable hoe, PaintType paint)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject piece in hoe.m_pieces)
			{
				if (!((Object)(object)piece == (Object)null) && !Plugin.IsOurPrefab(piece))
				{
					TerrainOp val = piece.GetComponent<TerrainOp>() ?? piece.GetComponentInChildren<TerrainOp>(true);
					if ((Object)(object)val != (Object)null && val.m_settings.m_paintType == paint)
					{
						return piece;
					}
				}
			}
			return null;
		}

		private static GameObject FindAnyTerrainPiece(PieceTable hoe)
		{
			foreach (GameObject piece in hoe.m_pieces)
			{
				if (!((Object)(object)piece == (Object)null) && !Plugin.IsOurPrefab(piece) && ((Object)(object)piece.GetComponent<TerrainOp>() != (Object)null || (Object)(object)piece.GetComponentInChildren<TerrainOp>(true) != (Object)null))
				{
					return piece;
				}
			}
			return null;
		}

		private static void RefreshPlayerPieces()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				Traverse.Create((object)localPlayer).Method("UpdateAvailablePiecesList", Array.Empty<object>()).GetValue();
			}
		}
	}
	internal static class Loc
	{
		private static bool _applying;

		public static bool IsRussian { get; private set; }

		public static void Apply()
		{
			Apply(Current());
		}

		public static void Apply(Localization loc)
		{
			if (loc == null || _applying)
			{
				return;
			}
			_applying = true;
			try
			{
				IsRussian = loc.GetSelectedLanguage() == "Russian";
				Add(loc, "flathoe_dirt", IsRussian ? "Плоский рельеф (земля)" : "Flat Hoe (dirt)");
				Add(loc, "flathoe_paved", IsRussian ? "Плоский рельеф (галька)" : "Flat Hoe (pebbles)");
				Add(loc, "flathoe_dirt_desc", IsRussian ? "Выравнивает грунт в идеально плоский участок и красит его землёй. ↑↓ размер, ← квадрат, → круг." : "Levels ground into a perfectly flat dirt pad. Up/Down size, Left square, Right circle.");
				Add(loc, "flathoe_paved_desc", IsRussian ? "Выравнивает грунт в идеально плоский участок и кладёт гальку / камень. ↑↓ размер, ← квадрат, → круг." : "Levels ground into a perfectly flat pebble / stone pad. Up/Down size, Left square, Right circle.");
			}
			catch (Exception arg)
			{
				Plugin.LogError($"Localization failed: {arg}");
			}
			finally
			{
				_applying = false;
			}
		}

		private static Localization Current()
		{
			return Traverse.Create(typeof(Localization)).Field<Localization>("m_instance").Value;
		}

		private static void Add(Localization loc, string key, string text)
		{
			Traverse.Create((object)loc).Method("AddWord", new object[2] { key, text }).GetValue();
		}
	}
	[HarmonyPatch(typeof(Localization), "SetupLanguage")]
	internal static class LocalizationSetupPatch
	{
		private static void Postfix(Localization __instance)
		{
			Loc.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(Localization), "SetLanguage")]
	internal static class LocalizationSetPatch
	{
		private static void Postfix(Localization __instance)
		{
			Loc.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class ZNetSceneAwakePatch
	{
		private static void Postfix()
		{
			try
			{
				HoeFlatPieces.TryRegister();
			}
			catch (Exception arg)
			{
				Plugin.LogError($"ZNetScene.Awake: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "OnDestroy")]
	internal static class ZNetSceneDestroyPatch
	{
		private static void Prefix()
		{
			try
			{
				HoeFlatPieces.Unregister();
			}
			catch (Exception arg)
			{
				Plugin.LogError($"ZNetScene.OnDestroy: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDbAwakePatch
	{
		private static void Postfix()
		{
			try
			{
				HoeFlatPieces.RegisterTerrainOps();
			}
			catch (Exception arg)
			{
				Plugin.LogError($"ObjectDB.Awake: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDbCopyPatch
	{
		private static void Postfix()
		{
			try
			{
				HoeFlatPieces.RegisterTerrainOps();
			}
			catch (Exception arg)
			{
				Plugin.LogError($"ObjectDB.CopyOtherDB: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
	internal static class PieceTableAvailablePatch
	{
		private static void Prefix(PieceTable __instance, HashSet<string> knownRecipies)
		{
			try
			{
				__instance?.m_pieces?.RemoveAll((GameObject p) => (Object)(object)p == (Object)null);
				knownRecipies?.Add("$flathoe_dirt");
				knownRecipies?.Add("$flathoe_paved");
			}
			catch (Exception arg)
			{
				Plugin.LogError($"PieceTable.UpdateAvailable: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	internal static class PlayerUpdatePatch
	{
		private static float _repeat;

		private static void Postfix(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				HoeFlatPieces.TryRegister();
				HoeFlatPieces.RegisterTerrainOps();
				if (!HoeFlatPieces.IsLocalToolActive() || Hud.IsPieceSelectionVisible() || Console.IsVisible() || Menu.IsVisible())
				{
					_repeat = 0f;
					return;
				}
				if (ZInput.GetKeyDown((KeyCode)276, false))
				{
					Plugin.SetSquare(square: true);
				}
				if (ZInput.GetKeyDown((KeyCode)275, false))
				{
					Plugin.SetSquare(square: false);
				}
				bool key = ZInput.GetKey((KeyCode)273, false);
				bool key2 = ZInput.GetKey((KeyCode)274, false);
				if (!key && !key2)
				{
					_repeat = 0f;
					return;
				}
				bool flag = ZInput.GetKeyDown((KeyCode)273, false) || ZInput.GetKeyDown((KeyCode)274, false);
				_repeat -= Time.deltaTime;
				if (flag || !(_repeat > 0f))
				{
					_repeat = (flag ? 0.25f : 0.07f);
					float value = Plugin.RadiusStep.Value;
					if (key)
					{
						Plugin.SetRadius(Plugin.CurrentRadius + value);
					}
					if (key2)
					{
						Plugin.SetRadius(Plugin.CurrentRadius - value);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.LogError($"Player.Update: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class GhostPatch
	{
		private static void Postfix(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				GameObject placementGhost = Plugin.GetPlacementGhost(__instance);
				if (!((Object)(object)placementGhost == (Object)null))
				{
					HoeFlatPieces.ApplyToGhost(placementGhost);
					PieceTable buildPieces = Plugin.GetBuildPieces(__instance);
					Piece val = (((Object)(object)buildPieces != (Object)null) ? buildPieces.GetSelectedPiece() : null);
					if ((Object)(object)val != (Object)null)
					{
						HoeFlatPieces.ApplyToGhost(((Component)val).gameObject);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.LogError($"UpdatePlacementGhost: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(TerrainOp), "Awake")]
	internal static class TerrainOpAwakePatch
	{
		private static void Prefix(TerrainOp __instance)
		{
			try
			{
				if (!TerrainOp.m_forceDisableTerrainOps && (Plugin.IsOurPrefab(((Component)__instance).gameObject) || Plugin.IsOurPrefab(((Component)((Component)__instance).transform.root).gameObject)))
				{
					HoeFlatPieces.ApplyToGhost(((Component)__instance).gameObject);
					HoeFlatPieces.ApplyRadiusToRegistered();
				}
			}
			catch (Exception arg)
			{
				Plugin.LogError($"TerrainOp.Awake: {arg}");
			}
		}
	}
	[BepInPlugin("com.valheimtools.flathoe", "Flat Hoe", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.valheimtools.flathoe";

		public const string ModName = "Flat Hoe";

		public const string ModVersion = "1.2.0";

		public const string DirtPrefab = "FlatHoe_Dirt";

		public const string PavedPrefab = "FlatHoe_Paved";

		public const string DirtToken = "$flathoe_dirt";

		public const string PavedToken = "$flathoe_paved";

		public const string DirtDescToken = "$flathoe_dirt_desc";

		public const string PavedDescToken = "$flathoe_paved_desc";

		public static ConfigEntry<float> Radius;

		public static ConfigEntry<float> MinRadius;

		public static ConfigEntry<float> MaxRadius;

		public static ConfigEntry<float> RadiusStep;

		public static ConfigEntry<bool> SmoothEdges;

		public static ConfigEntry<bool> SquareShape;

		public static ConfigEntry<bool> RequireResources;

		public static ConfigEntry<bool> ShowRadiusHud;

		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static float CurrentRadius { get; set; }

		public static bool UseSquare { get; set; }

		private void Awake()
		{
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			Instance = this;
			Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "Radius", 6f, "Starting flatten radius in meters. Change in-game with Up/Down arrows.");
			MinRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MinRadius", 1f, "Minimum radius the Up/Down arrows can set.");
			MaxRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxRadius", 16f, "Maximum radius the Up/Down arrows can set.");
			RadiusStep = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "RadiusStep", 0.5f, "Radius change per Up/Down arrow step.");
			SmoothEdges = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "SmoothEdges", false, "If true, blend the rim into nearby terrain. Leave false for a perfectly flat pad.");
			SquareShape = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "SquareShape", false, "Starting shape. In-game: Left arrow = square, Right arrow = circle.");
			RequireResources = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "RequireResources", false, "If true, keep the vanilla hoe costs (wood / stone). If false, flattening is free.");
			ShowRadiusHud = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowRadiusHud", true, "Show width, depth and shape next to the crosshair.");
			CurrentRadius = Mathf.Clamp(Radius.Value, MinRadius.Value, MaxRadius.Value);
			UseSquare = SquareShape.Value;
			try
			{
				_harmony = new Harmony("com.valheimtools.flathoe");
				_harmony.PatchAll();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony patch failed: {arg}");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Flat Hoe 1.2.0 loaded.");
		}

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

		private void OnGUI()
		{
			//IL_0096: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00ed: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			if (ShowRadiusHud.Value && HoeFlatPieces.IsLocalToolActive())
			{
				string arg = ((!UseSquare) ? (Loc.IsRussian ? "круг" : "circle") : (Loc.IsRussian ? "квадрат" : "square"));
				string text = (Loc.IsRussian ? $"Ширина  {FlatPreview.Width:0.0} м\nГлубина  {FlatPreview.LastDepth:0.0} м\n{arg}\n↑↓ размер   ← квадрат   → круг" : $"Width  {FlatPreview.Width:0.0} m\nDepth  {FlatPreview.LastDepth:0.0} m\n{arg}\n↑↓ size   ← square   → circle");
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor((float)Screen.width / 2f + 28f, (float)Screen.height / 2f - 42f, 480f, 96f);
				val.normal.textColor = Color.black;
				GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), text, val);
				val.normal.textColor = new Color(1f, 0.15f, 0.12f);
				GUI.Label(val2, text, val);
			}
		}

		public static void LogInfo(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}

		public static void LogError(string message)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)message);
			}
		}

		public static void SetRadius(float value)
		{
			CurrentRadius = Mathf.Clamp(value, MinRadius.Value, MaxRadius.Value);
			HoeFlatPieces.ApplyRadiusToRegistered();
		}

		public static void SetSquare(bool square)
		{
			UseSquare = square;
			SquareShape.Value = square;
			HoeFlatPieces.ApplyRadiusToRegistered();
		}

		public static Quaternion PlayerFlatRotation()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return Quaternion.identity;
			}
			Vector3 forward = ((Component)localPlayer).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f)
			{
				return Quaternion.identity;
			}
			return Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up);
		}

		public static Vector3 PlayerFlatForward()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return PlayerFlatRotation() * Vector3.forward;
		}

		public static GameObject GetPlacementGhost(Player player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				return Traverse.Create((object)player).Field<GameObject>("m_placementGhost").Value;
			}
			return null;
		}

		public static PieceTable GetBuildPieces(Player player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				return Traverse.Create((object)player).Field<PieceTable>("m_buildPieces").Value;
			}
			return null;
		}

		public static bool IsOurPrefab(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string prefabName = Utils.GetPrefabName(name);
			if (!(prefabName == "FlatHoe_Dirt"))
			{
				return prefabName == "FlatHoe_Paved";
			}
			return true;
		}

		public static bool IsOurPrefab(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				return IsOurPrefab(((Object)go).name);
			}
			return false;
		}

		public static PaintType PaintFor(GameObject go)
		{
			if ((((Object)(object)go != (Object)null) ? Utils.GetPrefabName(((Object)go).name) : string.Empty) == "FlatHoe_Paved")
			{
				return (PaintType)2;
			}
			return (PaintType)0;
		}
	}
	internal static class SquareOp
	{
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static class BeginOpPatch
		{
			private static void Prefix(Vector3 pos, Vector3 rot, Settings modifier)
			{
				//IL_0020: 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_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: 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)
				_active = IsOurSettings(modifier);
				_square = _active && modifier.m_square;
				_center = pos;
				_radius = modifier.m_levelRadius;
				_savedPaintRadius = modifier.m_paintRadius;
				if (((Vector3)(ref rot)).sqrMagnitude > 0.01f)
				{
					_forward = rot;
				}
				else
				{
					_forward = Plugin.PlayerFlatForward();
				}
				if (_square)
				{
					modifier.m_paintRadius = _radius * 1.42f;
				}
			}

			private static void Postfix(Settings modifier)
			{
				if (_active && modifier != null)
				{
					modifier.m_paintRadius = _savedPaintRadius;
				}
				_active = false;
				_square = false;
				_savedMask = null;
				_savedModified = null;
			}
		}

		[HarmonyPatch(typeof(TerrainComp), "LevelTerrain")]
		private static class LevelPatch
		{
			private static bool Prefix(TerrainComp __instance, Vector3 worldPos, float radius)
			{
				//IL_0073: 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_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: 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_0128: 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)
				if (!_square)
				{
					return true;
				}
				Traverse obj = Traverse.Create((object)__instance);
				Heightmap value = obj.Field<Heightmap>("m_hmap").Value;
				int value2 = obj.Field<int>("m_width").Value;
				float[] value3 = obj.Field<float[]>("m_levelDelta").Value;
				float[] value4 = obj.Field<float[]>("m_smoothDelta").Value;
				bool[] value5 = obj.Field<bool[]>("m_modifiedHeight").Value;
				if ((Object)(object)value == (Object)null || value3 == null)
				{
					return true;
				}
				int num = default(int);
				int num2 = default(int);
				value.WorldToVertex(worldPos, ref num, ref num2);
				Vector3 val = worldPos - ((Component)__instance).transform.position;
				int num3 = Mathf.CeilToInt(radius * 1.42f / value.m_scale);
				int num4 = value2 + 1;
				float num5 = (float)value2 * value.m_scale * 0.5f;
				Vector3 position = ((Component)value).transform.position;
				for (int i = num2 - num3; i <= num2 + num3; i++)
				{
					for (int j = num - num3; j <= num + num3; j++)
					{
						if (j >= 0 && i >= 0 && j < num4 && i < num4 && Contains(position + new Vector3((float)j * value.m_scale - num5, 0f, (float)i * value.m_scale - num5)))
						{
							float height = value.GetHeight(j, i);
							float num6 = val.y - height;
							int num7 = i * num4 + j;
							num6 += value4[num7];
							value4[num7] = 0f;
							value3[num7] += num6;
							value3[num7] = Mathf.Clamp(value3[num7], -8f, 8f);
							value5[num7] = true;
						}
					}
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(TerrainComp), "PaintCleared")]
		private static class PaintPatch
		{
			private static void Prefix(TerrainComp __instance)
			{
				if (_square)
				{
					Traverse obj = Traverse.Create((object)__instance);
					Color[] value = obj.Field<Color[]>("m_paintMask").Value;
					bool[] value2 = obj.Field<bool[]>("m_modifiedPaint").Value;
					if (value != null && value2 != null)
					{
						_savedMask = (Color[])value.Clone();
						_savedModified = (bool[])value2.Clone();
					}
				}
			}

			private static void Postfix(TerrainComp __instance)
			{
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: 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)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				if (!_square || _savedMask == null || _savedModified == null)
				{
					return;
				}
				Traverse obj = Traverse.Create((object)__instance);
				Heightmap value = obj.Field<Heightmap>("m_hmap").Value;
				Color[] value2 = obj.Field<Color[]>("m_paintMask").Value;
				bool[] value3 = obj.Field<bool[]>("m_modifiedPaint").Value;
				int value4 = obj.Field<int>("m_width").Value;
				int value5 = obj.Field<int>("m_pitch").Value;
				if ((Object)(object)value == (Object)null || value2 == null)
				{
					return;
				}
				int num = Mathf.CeilToInt(_radius * 1.42f / value.m_scale) + 2;
				int num2 = default(int);
				int num3 = default(int);
				value.WorldToVertexMask(_center, ref num2, ref num3);
				for (int i = num3 - num; i <= num3 + num; i++)
				{
					for (int j = num2 - num; j <= num2 + num; j++)
					{
						if (j >= 0 && i >= 0 && j <= value4 && i <= value4 && !Contains(value.VertexMaskToWorld(j, i)))
						{
							int num4 = i * value5 + j;
							if (num4 >= 0 && num4 < value2.Length)
							{
								value2[num4] = _savedMask[num4];
								value3[num4] = _savedModified[num4];
							}
						}
					}
				}
			}
		}

		private static bool _active;

		private static bool _square;

		private static Vector3 _center;

		private static Vector3 _forward;

		private static float _radius;

		private static float _savedPaintRadius;

		private static Color[] _savedMask;

		private static bool[] _savedModified;

		public static bool IsOurSettings(Settings modifier)
		{
			if (modifier == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			foreach (TerrainOp terrainOp in ObjectDB.instance.m_terrainOps)
			{
				if ((Object)(object)terrainOp != (Object)null && terrainOp.m_settings == modifier && Plugin.IsOurPrefab(((Component)terrainOp).gameObject))
				{
					return true;
				}
			}
			return false;
		}

		public static bool Contains(Vector3 world)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_003a: 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_0047: 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_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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0020: 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)
			Vector3 forward = _forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(forward.z, 0f, 0f - forward.x);
			Vector3 val2 = world - _center;
			val2.y = 0f;
			float num = val2.x * val.x + val2.z * val.z;
			float num2 = val2.x * forward.x + val2.z * forward.z;
			if (Mathf.Abs(num) <= _radius)
			{
				return Mathf.Abs(num2) <= _radius;
			}
			return false;
		}
	}
}