Decompiled source of OCDheim v0.1.5

plugins/OCDheim.dll

Decompiled 4 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OCDheim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OCDheim")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.1.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.5.0")]
namespace OCDheim;

[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
public static class PreciseBuildPieceSnapper
{
	private const float NeighbourhoodSize = 3.5f;

	private const float CollisionDetectionThreshold = 10f;

	private static readonly List<Piece> neighbourPieces = new List<Piece>();

	private static readonly List<Piece> snappableNeighbourPieces = new List<Piece>();

	private static bool ShouldOverrideVanillaValheim(ItemData tool)
	{
		return Keybindings.SnapModeEnabled && tool.IsHammer();
	}

	private static bool ShouldSkipCollisionDetection(Piece buildPiece)
	{
		return buildPiece.m_groundPiece || buildPiece.m_clipGround || buildPiece.m_clipEverything;
	}

	private static bool ShouldSnapInternally(Piece buildPiece)
	{
		return buildPiece.IsConstructionPiece() && Keybindings.PrecisionModeEnabled;
	}

	private static bool ShouldSnapExternally(Piece buildPiece)
	{
		return buildPiece.IsFurniturePiece();
	}

	public static void Postfix(bool flashGuardStone, Player __instance, GameObject ___m_placementGhost, int ___m_placeRayMask)
	{
		if ((Object)(object)___m_placementGhost != (Object)null && ___m_placementGhost.activeSelf)
		{
			ItemData rightItem = ((Humanoid)__instance).GetRightItem();
			Piece component = ___m_placementGhost.GetComponent<Piece>();
			int layerMask = ___m_placeRayMask - LayerMask.GetMask(new string[1] { "piece_nonsolid" });
			Keybindings.Refresh();
			if (Keybindings.GridModeEnabled)
			{
				PreciseGridModeSnapper.SnapToGroundGrid(rightItem, component, layerMask);
			}
			else if (ShouldOverrideVanillaValheim(rightItem))
			{
				SnapToNeighbourPiece(component, layerMask);
			}
		}
	}

	private static void SnapToNeighbourPiece(Piece buildPiece, int layerMask)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: 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_003d: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = DeterminePlayerPoV(layerMask);
		List<Piece> pieces = FindNeighbourPieces(val);
		if (ShouldSnapInternally(buildPiece))
		{
			SnapInternally(buildPiece, pieces);
		}
		else
		{
			if (!ShouldSnapExternally(buildPiece))
			{
				return;
			}
			SnapTree.TraversalResult? traversalResult = (Keybindings.PrecisionModeEnabled ? SnapTree.FindNearestSuperiorPrecisionSnapNodeTo(val, pieces) : SnapTree.FindNearestOrdinaryPrecisionSnapNodeTo(val, pieces));
			if (traversalResult.HasValue)
			{
				var (val2, perpendicularToPlayerPoV) = DetermineNeighbourPieceExit(traversalResult.Value.neighbourSnapNode, traversalResult.Value.neighbourPiece, layerMask);
				if (!ShouldSkipCollisionDetection(buildPiece))
				{
					SnapExternally(buildPiece, val2, perpendicularToPlayerPoV);
				}
				else
				{
					((Component)buildPiece).transform.position = val2;
				}
			}
		}
	}

	public static void SnapInternally(Piece buildPiece, List<Piece> neighbourPieces)
	{
		//IL_001c: 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: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		SnapTree.TraversalResult? traversalResult = SnapTree.FindNearestOrdinaryPrecisionSnapNodeCombinationOf(buildPiece, neighbourPieces);
		if (traversalResult.HasValue)
		{
			Transform transform = ((Component)buildPiece).transform;
			transform.position += (Vector3)traversalResult.Value.neighbourSnapNode - traversalResult.Value.buildPieceSnapNode;
		}
	}

	public static void SnapExternally(Piece buildPiece, Vector3 neighbourPieceExit, Vector3 perpendicularToPlayerPoV)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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_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)
		//IL_0027: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		((Component)buildPiece).transform.position = neighbourPieceExit + perpendicularToPlayerPoV * 10f;
		Vector3 buildPieceExit = DeterminePieceExit(buildPiece, neighbourPieceExit);
		SnapPiecesByExits(buildPiece, buildPieceExit, neighbourPieceExit, perpendicularToPlayerPoV);
	}

	private static (Vector3, Vector3) DetermineNeighbourPieceExit(SnapNode neighbourSnapNode, Piece neighbourPiece, int layerMask)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		Vector3 snapNode = PokeToMiddle(neighbourSnapNode, neighbourPiece);
		Vector3 val = DeterminePerpendicularToPlayerPoVOn(snapNode, layerMask);
		Vector3 observer = (Vector3)neighbourSnapNode + val;
		Vector3 item = DeterminePieceExit(neighbourPiece, observer);
		return (item, val);
	}

	private static Vector3 DeterminePlayerPoV(int layerMask)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: 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)
		Vector3 position = ((Component)GameCamera.instance).transform.position;
		Vector3 forward = ((Component)GameCamera.instance).transform.forward;
		RaycastHit val = default(RaycastHit);
		Physics.Raycast(position, forward, ref val, 10f, layerMask);
		return ((RaycastHit)(ref val)).point;
	}

	private static Vector3 DeterminePerpendicularToPlayerPoVOn(Vector3 snapNode, int layerMask)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//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_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_0033: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)GameCamera.instance).transform.position;
		Vector3 val = snapNode - position;
		RaycastHit val2 = default(RaycastHit);
		Physics.Raycast(position, val, ref val2, 10f, layerMask);
		return ((RaycastHit)(ref val2)).normal;
	}

	private static void GetAllPiecesInRadius(Vector3 p, float radius, List<Piece> pieces)
	{
		//IL_002a: 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)
		foreach (Piece s_allPiece in Piece.s_allPieces)
		{
			if (((Component)s_allPiece).gameObject.layer != Piece.s_ghostLayer && (double)Vector3.Distance(p, ((Component)s_allPiece).transform.position) < (double)radius)
			{
				pieces.Add(s_allPiece);
			}
		}
	}

	private static List<Piece> FindNeighbourPieces(Vector3 playerPoV)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		neighbourPieces.Clear();
		snappableNeighbourPieces.Clear();
		GetAllPiecesInRadius(playerPoV, 3.5f, neighbourPieces);
		foreach (Piece neighbourPiece in neighbourPieces)
		{
			if (neighbourPiece.IsSnappablePiece())
			{
				snappableNeighbourPieces.Add(neighbourPiece);
			}
		}
		return snappableNeighbourPieces;
	}

	private static Vector3 DeterminePieceExit(Piece piece, Vector3 observer)
	{
		//IL_000d: 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_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_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		float num = float.PositiveInfinity;
		Vector3 result = ((Component)piece).transform.position;
		Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>();
		Collider[] array = componentsInChildren;
		foreach (Collider val in array)
		{
			if (!val.enabled || val.isTrigger)
			{
				continue;
			}
			MeshCollider val2 = (MeshCollider)(object)((val is MeshCollider) ? val : null);
			if ((Object)(object)val2 == (Object)null || val2.convex)
			{
				Vector3 val3 = val.ClosestPoint(observer);
				float num2 = Vector3.Distance(observer, val3);
				if (num2 < num)
				{
					result = val3;
					num = num2;
				}
			}
		}
		return result;
	}

	private static Vector3 PokeToMiddle(Vector3 snapNode, Piece piece)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_001f: 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_0025: 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_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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)
		Vector3 val = ((Component)piece).transform.position - snapNode;
		Vector3 val2 = ((Vector3)(ref val)).normalized * 0.05f;
		return snapNode + val2;
	}

	private static void SnapPiecesByExits(Piece buildPiece, Vector3 buildPieceExit, Vector3 neighbourPieceEntry, Vector3 perpendicularToNeighbourPiece)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_0020: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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_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)
		Vector3 val = ((Component)buildPiece).transform.position - buildPieceExit;
		((Vector3)(ref val))..ctor(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z));
		val = Vector3.Scale(val, perpendicularToNeighbourPiece);
		((Component)buildPiece).transform.position = neighbourPieceEntry + val;
	}
}
public static class PreciseGridModeSnapper
{
	private const string LevelGroundToolName = "mud_road_v2";

	private const float MaxDrill = 5f;

	private static bool ShouldUsePlayerPositionAsGroundLevelReference(Piece piece)
	{
		return ((Object)piece).name == "mud_road_v2" && Keybindings.SnapModeEnabled;
	}

	private static bool ShouldUseDoublePrecision(ItemData tool)
	{
		return Keybindings.PrecisionModeEnabled && !tool.IsHoe();
	}

	public static void SnapToGroundGrid(ItemData tool, Piece piece, int layerMask)
	{
		//IL_0014: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		int num = ((!ShouldUseDoublePrecision(tool)) ? 1 : 2);
		float num2 = Mathf.Round(((Component)piece).transform.position.x * (float)num) / (float)num;
		float num3 = Mathf.Round(((Component)piece).transform.position.z * (float)num) / (float)num;
		if (ShouldUsePlayerPositionAsGroundLevelReference(piece))
		{
			((Component)piece).transform.position = new Vector3(num2, ((Component)piece).transform.position.y, num3);
		}
		else
		{
			Vector3? val = DeterminePreciseGroundPosition(piece, num2, num3, layerMask);
			if (val.HasValue)
			{
				PreciseBuildPieceSnapper.SnapExternally(piece, val.Value, Vector3.up);
			}
			else
			{
				((Component)piece).gameObject.SetActive(false);
			}
		}
		if (tool.IsTerrainModificationTool())
		{
			FixVanillaValheimBugWithSpinningTerrainModificationVFX(piece);
		}
	}

	private static Vector3? DeterminePreciseGroundPosition(Piece piece, float xOnGrid, float zOnGrid, int layerMask)
	{
		//IL_000a: 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_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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(xOnGrid, ((Component)piece).transform.position.y, zOnGrid);
		Vector3 drillFrom = val + new Vector3(0f, 2.5f, 0f);
		return RecursiveDrillDown(val, drillFrom, 5f, layerMask);
	}

	private static Vector3? RecursiveDrillDown(Vector3 referencePosition, Vector3 drillFrom, float drillTill, int layerMask)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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)
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(drillFrom, Vector3.down, ref val, drillTill, layerMask))
		{
			Vector3 point = ((RaycastHit)(ref val)).point;
			float num = drillTill - Vector3.Distance(drillFrom, point);
			if (drillTill - num > 0.001f)
			{
				Vector3? result = RecursiveDrillDown(referencePosition, point, num, layerMask);
				if (result.HasValue)
				{
					if (Vector3.Distance(referencePosition, point) > Vector3.Distance(referencePosition, result.Value))
					{
						return result;
					}
					return point;
				}
				return point;
			}
			return null;
		}
		return null;
	}

	private static void FixVanillaValheimBugWithSpinningTerrainModificationVFX(Piece piece)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		((Component)piece).transform.rotation = Quaternion.Euler(0f, 0f, 0f);
	}
}
public struct Box : ISide
{
	public char name { get; private set; }

	public Vector3 minMinSnapNode { get; private set; }

	public Vector3 minMaxSnapNode { get; private set; }

	public Vector3 maxMinSnapNode { get; private set; }

	public Vector3 maxMaxSnapNode { get; private set; }

	private SnapNode.Type primarySnapNodeType { get; set; }

	public Box(char name, Vector3 minMinSnapNode, Vector3 minMaxSnapNode, Vector3 maxMinSnapNode, Vector3 maxMaxSnapNode)
	{
		//IL_000a: 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_001a: 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)
		this.name = name;
		this.minMinSnapNode = minMinSnapNode;
		this.minMaxSnapNode = minMaxSnapNode;
		this.maxMinSnapNode = maxMinSnapNode;
		this.maxMaxSnapNode = maxMaxSnapNode;
		primarySnapNodeType = SnapNode.Type.PRIMARY;
	}

	public Box(Piece piece, Vector2 shift, char name = 'A')
	{
		//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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: 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_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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_0091: 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_009d: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		this.name = name;
		Vector3 val = piece.TopMiddlee();
		minMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, 0f - shift.y);
		minMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, shift.y);
		maxMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, 0f - shift.y);
		maxMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, shift.y);
		primarySnapNodeType = SnapNode.Type.IMPOSED;
	}

	public void FillUp(HashSet<SnapNode> snapNodes)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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_0014: 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_001f: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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_009d: 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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//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_00bf: 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_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		Vector3 dimensionΔ = minMaxSnapNode - minMinSnapNode;
		Vector3 dimensionΔ2 = maxMinSnapNode - minMinSnapNode;
		(Vector3, int) tuple = RecursiveSplit(dimensionΔ);
		Vector3 item = tuple.Item1;
		int item2 = tuple.Item2;
		(Vector3, int) tuple2 = RecursiveSplit(dimensionΔ2);
		Vector3 item3 = tuple2.Item1;
		int item4 = tuple2.Item2;
		double num = Math.Pow(2.0, item2) + 1.0;
		double num2 = Math.Pow(2.0, item4) + 1.0;
		for (int i = 0; (double)i < num; i++)
		{
			for (int j = 0; (double)j < num2; j++)
			{
				Vector3 position = minMinSnapNode + item * (float)i + item3 * (float)j;
				if ((i == 0 || (double)i == num - 1.0) && (j == 0 || (double)j == num2 - 1.0))
				{
					snapNodes.Add(new SnapNode(position, primarySnapNodeType, SnapNode.Precision.ORDINARY));
				}
				else if ((float)i % 2f == 0f && (float)j % 2f == 0f)
				{
					snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.ORDINARY));
				}
				else
				{
					snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.SUPERIOR));
				}
			}
		}
	}

	private (Vector3, int) RecursiveSplit(Vector3 dimensionΔ, int splitLevel = 0)
	{
		//IL_002f: 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_001b: Unknown result type (might be due to invalid IL or missing references)
		if (((Vector3)(ref dimensionΔ)).magnitude > 0.75f)
		{
			return RecursiveSplit(dimensionΔ * 0.5f, ++splitLevel);
		}
		return (dimensionΔ, splitLevel);
	}

	public override string ToString()
	{
		//IL_001c: 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_0038: 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)
		return $"Box {name}: ({minMinSnapNode}, {minMaxSnapNode}, {maxMinSnapNode}, {maxMaxSnapNode})";
	}
}
public static class GroundLevelSpinner
{
	public const float MaxSpinner = 1f;

	public const float MinSpinner = 0f;

	public static float value { get; private set; } = 1f;


	public static void Refresh()
	{
		float num = Keybindings.ScrollΔ();
		if (num > 0f)
		{
			up(num);
		}
		if (num < 0f)
		{
			down(num);
		}
	}

	private static void up(float scrollΔ)
	{
		if (value + scrollΔ > 1f)
		{
			value = 1f;
		}
		else
		{
			value = Mathf.Round((value + scrollΔ) * 100f) / 100f;
		}
	}

	private static void down(float scrollΔ)
	{
		if (value + scrollΔ < 0f)
		{
			value = 0f;
		}
		else
		{
			value = Mathf.Round((value + scrollΔ) * 100f) / 100f;
		}
	}
}
public static class ToolHelper
{
	private const string HoeToolName = "$item_hoe";

	private const string HammerToolName = "$item_hammer";

	private const string CultivatorToolName = "$item_cultivator";

	public static bool IsHoe(this ItemData tool)
	{
		return tool.m_shared.m_name == "$item_hoe";
	}

	public static bool IsHammer(this ItemData tool)
	{
		return tool.m_shared.m_name == "$item_hammer";
	}

	public static bool IsCultivator(this ItemData tool)
	{
		return tool.m_shared.m_name == "$item_cultivator";
	}

	public static bool IsTerrainModificationTool(this ItemData tool)
	{
		return tool.IsHoe() || tool.IsCultivator();
	}
}
public class HoverInfo
{
	private GameObject go { get; }

	private Transform transform { get; }

	private TextMesh textMesh { get; }

	public string text
	{
		get
		{
			return textMesh.text;
		}
		set
		{
			textMesh.text = value;
		}
	}

	public bool enabled
	{
		get
		{
			return go.activeSelf;
		}
		set
		{
			go.SetActive(value);
		}
	}

	public Color color
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return textMesh.color;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			textMesh.color = value;
		}
	}

	public HoverInfo(Transform parentTransform)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Expected O, but got Unknown
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		go = new GameObject();
		go.transform.parent = parentTransform;
		transform = go.transform;
		textMesh = go.AddComponent<TextMesh>();
		((Component)textMesh).transform.localPosition = Vector3.zero;
		((Component)textMesh).transform.localScale = new Vector3(0.1f / parentTransform.localScale.x, 0.1f / parentTransform.localScale.y, 0.1f / parentTransform.localScale.z);
		textMesh.anchor = (TextAnchor)4;
		textMesh.alignment = (TextAlignment)1;
		textMesh.fontSize = 16;
	}

	public void RotateToPlayer()
	{
		//IL_000d: 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_0031: 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)
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(((Component)GameCamera.m_instance).transform.position.x, transform.position.y, ((Component)GameCamera.m_instance).transform.position.z);
		transform.LookAt(val, Vector3.up);
		transform.Rotate(90f, 180f, 0f);
	}
}
[HarmonyPatch(typeof(ZInput), "Load")]
public static class Keybindings
{
	public const string GridMode = "GridMode";

	public const string NoSnapMode = "AltPlace";

	public const string JoyGridMode = "JoyGridMode";

	public const string JoyNoSnapMode = "JoyAltPlace";

	public const string PrecisionMode = "PrecisionMode";

	public const string JoyPrecisionMode = "JoyPrecisionMode";

	public const string MouseScrollWheel = "Mouse ScrollWheel";

	public const string JoyScrollUnlock = "JoyLTrigger";

	public const string JoyScrollDOwn = "JoyDPadDown";

	public const string JoyScrollUp = "JoyDPadUp";

	public const float OrdinaryScrollPrecision = 0.05f;

	public const float SuperiorScrollPrecisionMulltiplier = 0.2f;

	private static bool gridModeFreshlyEnabled;

	private static bool gridModeFreshlyDisabled;

	public static bool GridModeEnabled { get; private set; }

	public static bool GridModeDisabled => !GridModeEnabled;

	public static bool GridModFreshlyEnabled
	{
		get
		{
			bool result = gridModeFreshlyEnabled;
			gridModeFreshlyEnabled = false;
			return result;
		}
	}

	public static bool GridModFreshlyDisabled
	{
		get
		{
			bool result = gridModeFreshlyDisabled;
			gridModeFreshlyDisabled = false;
			return result;
		}
	}

	public static bool PrecisionModeEnabled { get; private set; }

	public static bool PrecisionModeDisabled => !PrecisionModeEnabled;

	public static bool SnapModeEnabled => !ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyAltPlace");

	public static bool SnapModeDisabled => !SnapModeEnabled;

	public static void Postfix(ZInput __instance)
	{
		__instance.AddButton("PrecisionMode", (Key)40, 0f, 0f, true, false);
		__instance.AddButton("GridMode", (Key)53, 0f, 0f, true, false);
		__instance.AddButton("JoyGridMode", (GamepadInput)2, 0f, 0f, true, false);
		__instance.AddButton("JoyPrecisionMode", (GamepadInput)4, 0f, 0f, true, false);
	}

	public static void Refresh()
	{
		if (ZInput.GetButtonDown("GridMode") || ZInput.GetButtonDown("JoyGridMode"))
		{
			GridModeEnabled = !GridModeEnabled;
			gridModeFreshlyEnabled = GridModeEnabled;
			gridModeFreshlyDisabled = GridModeDisabled;
		}
		if (ZInput.GetButtonDown("PrecisionMode") || ZInput.GetButtonDown("JoyPrecisionMode"))
		{
			PrecisionModeEnabled = !PrecisionModeEnabled;
		}
	}

	public static float ScrollΔ()
	{
		float num = Input.GetAxis("Mouse ScrollWheel");
		if (num != 0f)
		{
			num = ((num > 0f) ? 0.05f : (-0.05f));
		}
		else if (ZInput.GetButton("JoyLTrigger"))
		{
			Debug.Log((object)"DUPA");
			num = (ZInput.GetButtonDown("JoyDPadUp") ? 0.05f : num);
			num = (ZInput.GetButtonDown("JoyDPadDown") ? (-0.05f) : num);
		}
		return PrecisionModeDisabled ? num : (num * 0.2f);
	}
}
public class Overlay
{
	private GameObject go { get; }

	private Particle[] particles { get; } = (Particle[])(object)new Particle[2];


	public Transform transform { get; }

	public ParticleSystem ps { get; }

	public ParticleSystemRenderer psr { get; }

	public MainModule psm { get; }

	public bool enabled
	{
		get
		{
			return go.activeSelf;
		}
		set
		{
			go.SetActive(value);
		}
	}

	public Vector3 position
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return transform.position;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			transform.position = value;
		}
	}

	public Vector3 locPosition
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return transform.localPosition;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			transform.localPosition = value;
		}
	}

	public Quaternion rotation
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return transform.rotation;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			transform.rotation = value;
		}
	}

	public Color color
	{
		get
		{
			//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_0030: 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)
			ps.GetParticles(particles, 2);
			return Color32.op_Implicit(((Particle)(ref particles[1])).GetCurrentColor(ps));
		}
	}

	public Color startColor
	{
		get
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			MainModule val = psm;
			MinMaxGradient val2 = ((MainModule)(ref val)).startColor;
			return ((MinMaxGradient)(ref val2)).color;
		}
		set
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0012: Unknown result type (might be due to invalid IL or missing references)
			MainModule val = psm;
			MinMaxGradient val2 = ((MainModule)(ref val)).startColor;
			((MinMaxGradient)(ref val2)).color = value;
		}
	}

	public float startSize
	{
		get
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			MainModule val = psm;
			MinMaxCurve val2 = ((MainModule)(ref val)).startSize;
			return ((MinMaxCurve)(ref val2)).constant;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			MainModule main = ps.main;
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(value);
		}
	}

	public float startSpeed
	{
		get
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			MainModule val = psm;
			MinMaxCurve val2 = ((MainModule)(ref val)).startSize;
			return ((MinMaxCurve)(ref val2)).constant;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			MainModule main = ps.main;
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(value);
		}
	}

	public float startLifetime
	{
		get
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			MainModule val = psm;
			MinMaxCurve val2 = ((MainModule)(ref val)).startLifetime;
			return ((MinMaxCurve)(ref val2)).constant;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			MainModule main = ps.main;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(value);
		}
	}

	public bool sizeOverLifetimeEnabled
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			SizeOverLifetimeModule val = ps.sizeOverLifetime;
			return ((SizeOverLifetimeModule)(ref val)).enabled;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			SizeOverLifetimeModule val = ps.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref val)).enabled = value;
		}
	}

	public MinMaxCurve sizeOverLifetime
	{
		get
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			SizeOverLifetimeModule val = ps.sizeOverLifetime;
			return ((SizeOverLifetimeModule)(ref val)).size;
		}
		set
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			SizeOverLifetimeModule val = ps.sizeOverLifetime;
			((SizeOverLifetimeModule)(ref val)).size = value;
		}
	}

	public Overlay(Transform transform)
	{
		this.transform = transform;
		go = ((Component)transform).gameObject;
		ps = ((Component)transform).GetComponentInChildren<ParticleSystem>();
		psr = ((Component)transform).GetComponentInChildren<ParticleSystemRenderer>();
	}
}
public abstract class OverlayVisualizer : MonoBehaviour
{
	protected Overlay primary;

	protected Overlay secondary;

	protected Overlay tetriary;

	protected HoverInfo hoverInfo;

	public static Texture2D remove => OCDheim.LoadTextureFromDisk("remove.png");

	public static Texture2D cross => OCDheim.LoadTextureFromDisk("cross.png");

	public static Texture2D undo => OCDheim.LoadTextureFromDisk("undo.png");

	public static Texture2D redo => OCDheim.LoadTextureFromDisk("redo.png");

	public static Texture2D box => OCDheim.LoadTextureFromDisk("box.png");

	private void Update()
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		if (primary == null)
		{
			Transform val = ((Component)this).transform.Find("_GhostOnly");
			Transform val2 = Object.Instantiate<Transform>(val, ((Component)this).transform);
			Transform transform = Object.Instantiate<Transform>(val2, ((Component)this).transform);
			primary = new Overlay(val);
			secondary = new Overlay(val2);
			tetriary = new Overlay(transform);
			hoverInfo = new HoverInfo(val2);
			tetriary.startColor = new Color(255f, 255f, 255f);
			primary.enabled = false;
			secondary.enabled = false;
			tetriary.enabled = false;
			Initialize();
		}
		if (Keybindings.GridModFreshlyEnabled)
		{
			OnEnableGrid();
		}
		if (Keybindings.GridModFreshlyDisabled)
		{
			OnDisableGrid();
		}
		OnRefresh();
	}

	protected abstract void Initialize();

	protected abstract void OnRefresh();

	protected abstract void OnEnableGrid();

	protected abstract void OnDisableGrid();

	protected void SpeedUp(Overlay ov)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		AnimationCurve val = new AnimationCurve();
		val.AddKey(0f, 0f);
		val.AddKey(0.5f, 1f);
		MinMaxCurve sizeOverLifetime = default(MinMaxCurve);
		((MinMaxCurve)(ref sizeOverLifetime))..ctor(1f, val);
		ov.startLifetime = 2f;
		ov.sizeOverLifetime = sizeOverLifetime;
	}

	protected void Freeze(Overlay ov)
	{
		ov.startSpeed = 0f;
		ov.sizeOverLifetimeEnabled = false;
	}

	protected void VisualizeTerraformingBounds(Overlay ov)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		ov.startSize = 3f;
		((Renderer)ov.psr).material.mainTexture = (Texture)(object)box;
		ov.locPosition = new Vector3(0f, 0.05f, 0f);
	}

	protected void VisualizeRecoloringBounds(Overlay ov)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		ov.startSize = 4f;
		((Renderer)ov.psr).material.mainTexture = (Texture)(object)box;
		ov.locPosition = new Vector3(0.5f, 0.05f, 0.5f);
	}

	protected void VisualizeIconInsideTerraformingBounds(Overlay ov, Texture iconTexture)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		ov.startSize = 2.5f;
		((Renderer)ov.psr).material.mainTexture = iconTexture;
		ov.locPosition = new Vector3(0f, 0.05f, 0f);
	}

	protected void VisualizeIconInsideRecoloringBounds(Overlay ov, Texture iconTexture)
	{
		//IL_0026: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		ov.startSize = 3f;
		((Renderer)ov.psr).material.mainTexture = iconTexture;
		ov.position = ((Component)this).transform.position + new Vector3(0.5f, 0.05f, 0.5f);
	}
}
public abstract class HoverInfoEnabled : OverlayVisualizer
{
	protected override void Initialize()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		hoverInfo.color = secondary.startColor;
	}

	protected override void OnRefresh()
	{
		//IL_002e: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		if (hoverInfo.enabled)
		{
			hoverInfo.RotateToPlayer();
			hoverInfo.text = $"x: {secondary.position.x:0}, y: {secondary.position.z:0}, h: {secondary.position.y - 0.05f:0.00000}";
		}
	}

	protected override void OnEnableGrid()
	{
	}

	protected override void OnDisableGrid()
	{
	}
}
public abstract class SecondaryEnabledOnGridModePrimaryDisabledOnGridMode : HoverInfoEnabled
{
	protected override void OnRefresh()
	{
		base.OnRefresh();
		primary.enabled = Keybindings.GridModeDisabled;
		secondary.enabled = Keybindings.GridModeEnabled;
	}
}
public abstract class SecondaryEnabledOnGridModePrimaryEnabledAlways : HoverInfoEnabled
{
	protected override void OnRefresh()
	{
		base.OnRefresh();
		primary.enabled = true;
		secondary.enabled = Keybindings.GridModeEnabled;
	}
}
public abstract class SecondaryAndPrimaryEnabledAlways : OverlayVisualizer
{
	protected override void OnRefresh()
	{
		primary.enabled = true;
		secondary.enabled = true;
	}

	protected override void OnEnableGrid()
	{
	}

	protected override void OnDisableGrid()
	{
	}
}
[HarmonyPatch(typeof(Piece), "SetInvalidPlacementHeightlight")]
public static class OverlayVisualizationRedshiftHeighlightBlocker
{
	private static bool Prefix(bool enabled, Piece __instance)
	{
		return (Object)(object)((Component)__instance).GetComponentInChildren<OverlayVisualizer>() == (Object)null;
	}
}
public class LevelGroundOverlayVisualizer : SecondaryEnabledOnGridModePrimaryDisabledOnGridMode
{
	protected override void Initialize()
	{
		base.Initialize();
		SpeedUp(secondary);
		VisualizeTerraformingBounds(secondary);
	}
}
public class RaiseGroundOverlayVisualizer : SecondaryEnabledOnGridModePrimaryEnabledAlways
{
	protected override void Initialize()
	{
		base.Initialize();
		Freeze(secondary);
		Freeze(tetriary);
		VisualizeTerraformingBounds(secondary);
		VisualizeTerraformingBounds(tetriary);
	}

	protected override void OnRefresh()
	{
		//IL_0030: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		base.OnRefresh();
		if (Keybindings.GridModeEnabled)
		{
			GroundLevelSpinner.Refresh();
			secondary.locPosition = new Vector3(0f, GroundLevelSpinner.value, 0f);
			if (GroundLevelSpinner.value > 0f)
			{
				hoverInfo.text = $"h: +{secondary.locPosition.y:0.00}";
			}
			else
			{
				hoverInfo.text = $"x: {secondary.position.x:0}, y: {secondary.position.z:0}, h: {secondary.position.y:0.00000}";
			}
		}
		tetriary.enabled = Keybindings.GridModeEnabled;
	}
}
public class PaveRoadOverlayVisualizer : SecondaryEnabledOnGridModePrimaryDisabledOnGridMode
{
	protected override void Initialize()
	{
		base.Initialize();
		SpeedUp(secondary);
		VisualizeRecoloringBounds(secondary);
	}
}
public class CultivateOverlayVisualizer : PaveRoadOverlayVisualizer
{
	protected override void OnRefresh()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		base.OnRefresh();
		hoverInfo.color = secondary.color;
	}
}
public class SeedGrassOverlayVisualizer : SecondaryEnabledOnGridModePrimaryEnabledAlways
{
	protected override void Initialize()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		base.Initialize();
		Freeze(secondary);
		VisualizeRecoloringBounds(secondary);
		primary.locPosition = new Vector3(0f, 2f, 0f);
	}

	protected override void OnRefresh()
	{
		//IL_0066: 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 (Keybindings.GridModeEnabled)
		{
			primary.startSize = 4f;
			primary.locPosition = new Vector3(0.5f, 2.5f, 0.5f);
		}
		else
		{
			primary.startSize = 5.5f;
			primary.locPosition = new Vector3(0f, 2.5f, 0f);
		}
		base.OnRefresh();
	}

	protected override void OnEnableGrid()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		base.OnEnableGrid();
		primary.enabled = false;
		primary.startSize = 4f;
		primary.locPosition = new Vector3(0.5f, 2.5f, 0.5f);
		primary.enabled = true;
	}

	protected override void OnDisableGrid()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		primary.enabled = false;
		primary.locPosition = new Vector3(0f, 2.5f, 0f);
		primary.startSize = 5.5f;
		primary.enabled = true;
		base.OnDisableGrid();
	}
}
public class RemoveModificationsOverlayVisualizer : SecondaryAndPrimaryEnabledAlways
{
	protected override void Initialize()
	{
		Freeze(primary);
		SpeedUp(secondary);
		VisualizeTerraformingBounds(primary);
		VisualizeIconInsideTerraformingBounds(secondary, (Texture)(object)OverlayVisualizer.cross);
	}
}
public abstract class UndoRedoModificationsOverlayVisualizer : SecondaryAndPrimaryEnabledAlways
{
	protected override void Initialize()
	{
		Freeze(primary);
		Freeze(secondary);
		VisualizeRecoloringBounds(primary);
		VisualizeIconInsideRecoloringBounds(secondary, (Texture)(object)icon());
	}

	protected abstract Texture2D icon();
}
public class UndoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer
{
	protected override Texture2D icon()
	{
		return OverlayVisualizer.undo;
	}
}
public class RedoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer
{
	protected override Texture2D icon()
	{
		return OverlayVisualizer.redo;
	}
}
public static class PieceHelpers
{
	public static readonly Dictionary<string, Func<Piece, ISide>> SnappableFurniturePieces = new Dictionary<string, Func<Piece, ISide>>
	{
		["$piece_table_oak"] = (Piece piece) => new Box(piece, new Vector2(3f, 0.8f)),
		["$piece_blackmarble_table"] = (Piece piece) => new Box(piece, new Vector2(1.15f, 0.5f)),
		["$piece_table"] = (Piece piece) => new Box(piece, new Vector2(1.1f, 0.475f)),
		["$piece_table_round"] = (Piece piece) => new Circle(piece, new Vector2(1.15f, 0f))
	};

	private static readonly List<Transform> primarySPs = new List<Transform>();

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

	private static Piece thisPiece = null;

	public static bool IsConstructionPiece(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count != 0, "CONSTRUCTION");
	}

	public static bool IsFurniturePiece(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count == 0, "FURNITURE");
	}

	public static bool IsSnappableFurniturePiece(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => piece.IsFurniturePiece() && SnappableFurniturePieces.ContainsKey(piece.m_name), "SNAPPABLE FURNITURE");
	}

	public static bool IsSnappablePiece(this Piece piece)
	{
		return piece.IsConstructionPiece() || piece.IsSnappableFurniturePiece();
	}

	public static bool IsLine(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count == 2, "LINE");
	}

	public static bool IsBox(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count == 4 && piece.EverySnapNodeLiesOnExtremums(), "BOX");
	}

	public static bool IsCube(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count == 8 && piece.EverySnapNodeLiesOnExtremums(), "CUBE");
	}

	public static bool IsCylinder(this Piece piece)
	{
		return piece.IsType((List<Vector3> snapNodes) => snapNodes.Count == 18, "CYLINDER");
	}

	public static List<Vector3> PrimarySnapNodesDefensiveCopy(this Piece piece)
	{
		return new List<Vector3>(primarySNs);
	}

	public static List<Vector3> PrimarySnapNodes(this Piece piece)
	{
		piece.FlushWhenRequired();
		return primarySNs;
	}

	public static Vector3 TopMiddlee(this Piece piece)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>();
		Bounds bounds = ((Component)piece).GetComponentInChildren<Collider>().bounds;
		Collider[] array = componentsInChildren;
		foreach (Collider val in array)
		{
			((Bounds)(ref bounds)).Encapsulate(val.bounds);
		}
		float y = ((Bounds)(ref bounds)).max.y;
		return new Vector3(((Component)piece).transform.position.x, y, ((Component)piece).transform.position.z);
	}

	private static void FlushWhenRequired(this Piece piece)
	{
		if ((Object)(object)thisPiece != (Object)(object)piece)
		{
			thisPiece = piece;
			primarySPs.Clear();
			primarySNs.Clear();
			piece.PopulatePrimarySnapNodes();
		}
	}

	private static bool IsType(this Piece piece, Func<List<Vector3>, bool> isShape, string shapeName)
	{
		piece.FlushWhenRequired();
		if (isShape(primarySNs))
		{
			return true;
		}
		return false;
	}

	private static void PopulatePrimarySnapNodes(this Piece piece)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		piece.GetSnapPoints(primarySPs);
		foreach (Transform primarySP in primarySPs)
		{
			primarySNs.Add(((Component)primarySP).transform.position);
		}
	}

	private static bool EverySnapNodeLiesOnExtremums(this Piece piece)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		Vector3 minimums = piece.SolveMinimumsOf();
		Vector3 maximums = piece.SolveMaximumsOf();
		foreach (Vector3 primarySN in primarySNs)
		{
			if (!LiesOnExtremums(primarySN, minimums, maximums))
			{
				return false;
			}
		}
		return true;
	}

	private static Vector3 SolveMinimumsOf(this Piece piece)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0088: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		float num = float.PositiveInfinity;
		float num2 = float.PositiveInfinity;
		float num3 = float.PositiveInfinity;
		foreach (Vector3 primarySN in primarySNs)
		{
			num = ((num > primarySN.x) ? primarySN.x : num);
			num2 = ((num2 > primarySN.y) ? primarySN.y : num2);
			num3 = ((num3 > primarySN.z) ? primarySN.z : num3);
		}
		return new Vector3(num, num2, num3);
	}

	private static Vector3 SolveMaximumsOf(this Piece piece)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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_0088: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		float num = float.NegativeInfinity;
		float num2 = float.NegativeInfinity;
		float num3 = float.NegativeInfinity;
		foreach (Vector3 primarySN in primarySNs)
		{
			num = ((num < primarySN.x) ? primarySN.x : num);
			num2 = ((num2 < primarySN.y) ? primarySN.y : num2);
			num3 = ((num3 < primarySN.z) ? primarySN.z : num3);
		}
		return new Vector3(num, num2, num3);
	}

	private static bool LiesOnExtremums(Vector3 snapNode, Vector3 minimums, Vector3 maximums)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: 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_002c: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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)
		if (snapNode.x != minimums.x && snapNode.x != maximums.x)
		{
			return false;
		}
		if (snapNode.y != minimums.y && snapNode.y != maximums.y)
		{
			return false;
		}
		if (snapNode.z != minimums.z && snapNode.z != maximums.z)
		{
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
public static class PreciseTerrainModifier
{
	public const int SizeInTiles = 1;

	private static bool Prefix(Vector3 pos, Settings modifier, Heightmap ___m_hmap, int ___m_width, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedHeight, ref bool[] ___m_modifiedPaint)
	{
		//IL_002a: 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 (!modifier.m_level && !modifier.m_raise && !modifier.m_smooth && !modifier.m_paintCleared)
		{
			RemoveTerrainModifications(pos, ___m_hmap, ___m_width, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight);
			RecolorTerrain(pos, (PaintType)3, ___m_hmap, ___m_width, ref ___m_paintMask, ref ___m_modifiedPaint);
		}
		return true;
	}

	public static void SmoothenTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, int worldWidth, ref float[] smoothΔ, ref bool[] modifiedHeight)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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)
		Debug.Log((object)"[INIT] Smooth Terrain Modification");
		int num = worldWidth + 1;
		int num2 = default(int);
		int num3 = default(int);
		hMap.WorldToVertex(worldPos, ref num2, ref num3);
		float num4 = worldPos.y - ((Component)compiler).transform.position.y;
		Debug.Log((object)$"worldPos: {worldPos}, xPos: {num2}, yPos: {num3}, referenceH: {num4}");
		FindExtremums(num2, num, out var xMin, out var xMax);
		FindExtremums(num3, num, out var xMin2, out var xMax2);
		for (int i = xMin; i <= xMax; i++)
		{
			for (int j = xMin2; j <= xMax2; j++)
			{
				int num5 = j * num + i;
				float height = hMap.GetHeight(i, j);
				float num6 = num4 - height;
				float num7 = smoothΔ[num5];
				float num8 = num7 + num6;
				float num9 = RoundToTwoDecimals(height, num7, num8);
				float num10 = Mathf.Clamp(num9, -1f, 1f);
				smoothΔ[num5] = num10;
				modifiedHeight[num5] = true;
				Debug.Log((object)$"tilePos: ({i}, {j}), tileH: {height}, Δh: {num6}, oldΔh: {num7}, newΔh: {num8}, roundedNewΔh: {num9}, limΔh: {num10}");
			}
		}
		Debug.Log((object)"[SUCCESS] Smooth Terrain Modification");
	}

	public static void RaiseTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, int worldWidth, float power, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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)
		Debug.Log((object)"[INIT] Raise Terrain Modification");
		int num = worldWidth + 1;
		int num2 = default(int);
		int num3 = default(int);
		hMap.WorldToVertex(worldPos, ref num2, ref num3);
		float num4 = worldPos.y - ((Component)compiler).transform.position.y + power;
		Debug.Log((object)$"worldPos: {worldPos}, xPos: {num2}, yPos: {num3}, power: {power}, referenceH: {num4}");
		FindExtremums(num2, num, out var xMin, out var xMax);
		FindExtremums(num3, num, out var xMin2, out var xMax2);
		for (int i = xMin; i <= xMax; i++)
		{
			for (int j = xMin2; j <= xMax2; j++)
			{
				int num5 = j * num + i;
				float height = hMap.GetHeight(i, j);
				float num6 = num4 - height;
				if (num6 >= 0f)
				{
					float num7 = levelΔ[num5];
					float num8 = smoothΔ[num5];
					float num9 = num7 + num8 + num6;
					float num10 = 0f;
					float num11 = RoundToTwoDecimals(height, num7 + num8, num9 + num10);
					float num12 = Mathf.Clamp(num11, -16f, 16f);
					levelΔ[num5] = num12;
					smoothΔ[num5] = num10;
					modifiedHeight[num5] = true;
					Debug.Log((object)$"tilePos: ({i}, {j}), tileH: {height}, Δh: {num6}, oldLevelΔ: {num7}, oldSmoothΔ: {num8}, newLevelΔ: {num9}, newSmoothΔ: {num10}, roundedNewLevelΔ: {num11}, limitedNewLevelΔ: {num12}");
				}
				else
				{
					Debug.Log((object)"Declined to process tile: Δh < 0!");
					Debug.Log((object)$"tilePos: ({i}, {j}), tileH: {height}, Δh: {num6}");
				}
			}
		}
		Debug.Log((object)"[SUCCESS] Raise Terrain Modification");
	}

	public static void RecolorTerrain(Vector3 worldPos, PaintType paintType, Heightmap hMap, int worldWidth, ref Color[] paintMask, ref bool[] modifiedPaint)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		Debug.Log((object)"[INIT] Color Terrain Modification");
		worldPos -= new Vector3(0.5f, 0f, 0.5f);
		int num = default(int);
		int num2 = default(int);
		hMap.WorldToVertex(worldPos, ref num, ref num2);
		Debug.Log((object)$"worldPos: {worldPos}, vertexPos: ({num}, {num2})");
		Color val = ResolveColor(paintType);
		bool flag = val == Color.black;
		FindExtremums(num, worldWidth, out var xMin, out var xMax);
		FindExtremums(num2, worldWidth, out var xMin2, out var xMax2);
		for (int i = xMin; i <= xMax; i++)
		{
			for (int j = xMin2; j <= xMax2; j++)
			{
				int num3 = j * worldWidth + i;
				paintMask[num3] = val;
				modifiedPaint[num3] = !flag;
				Debug.Log((object)$"tilePos: ({i}, {j}), tileIndex: {num3}, tileColor: {val}");
			}
		}
		Debug.Log((object)"[SUCCESS] Color Terrain Modification");
	}

	public static void RemoveTerrainModifications(Vector3 worldPos, Heightmap hMap, int worldWidth, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight)
	{
		//IL_0011: 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)
		Debug.Log((object)"[INIT] Remove Terrain Modifications");
		int num = worldWidth + 1;
		int num2 = default(int);
		int num3 = default(int);
		hMap.WorldToVertex(worldPos, ref num2, ref num3);
		Debug.Log((object)$"worldPos: {worldPos}, vertexPos: ({num2}, {num3})");
		FindExtremums(num2, num, out var xMin, out var xMax);
		FindExtremums(num3, num, out var xMin2, out var xMax2);
		for (int i = xMin; i <= xMax; i++)
		{
			for (int j = xMin2; j <= xMax2; j++)
			{
				int num4 = j * num + i;
				levelΔ[num4] = 0f;
				smoothΔ[num4] = 0f;
				modifiedHeight[num4] = false;
				Debug.Log((object)$"tilePos: ({i}, {j}), tileIndex: {num4}");
			}
		}
		Debug.Log((object)"[SUCCESS] Remove Terrain Modifications");
	}

	public static Color ResolveColor(PaintType paintType)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Invalid comparison between Unknown and I4
		//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_003c: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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)paintType == 0)
		{
			return Color.red;
		}
		if ((int)paintType == 2)
		{
			return Color.blue;
		}
		if ((int)paintType == 1)
		{
			return Color.green;
		}
		return Color.black;
	}

	public static void FindExtremums(int x, int worldSize, out int xMin, out int xMax)
	{
		xMin = Mathf.Max(0, x - 1);
		xMax = Mathf.Min(x + 1, worldSize - 1);
	}

	public static float RoundToTwoDecimals(float oldH, float oldΔh, float newΔh)
	{
		float num = oldH - oldΔh + newΔh;
		float num2 = Mathf.Round(num * 100f) / 100f;
		float num3 = num2 - oldH + oldΔh;
		Debug.Log((object)$"oldH: {oldH}, oldΔH: {oldΔh}, newΔH: {newΔh}, newH: {num}, roundedNewH: {num2}, roundedNewΔh: {num3}");
		return num3;
	}
}
[HarmonyPatch(typeof(TerrainComp), "SmoothTerrain")]
public static class PreciseSmoothTerrainModification
{
	private static bool Prefix(Vector3 worldPos, float radius, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, int ___m_width, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		if (ClientSideGridModeOverride.IsGridModeEnabled(radius))
		{
			PreciseTerrainModifier.SmoothenTerrain(worldPos, ___m_hmap, __instance, ___m_width, ref ___m_smoothDelta, ref ___m_modifiedHeight);
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")]
public static class PreciseRaiseTerrainModification
{
	private static bool Prefix(Vector3 worldPos, float radius, float delta, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, int ___m_width, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		if (ClientSideGridModeOverride.IsGridModeEnabled(radius))
		{
			PreciseTerrainModifier.RaiseTerrain(worldPos, ___m_hmap, __instance, ___m_width, delta, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight);
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(TerrainComp), "PaintCleared")]
public static class PreciseColorTerrainModification
{
	private static bool Prefix(Vector3 worldPos, float radius, PaintType paintType, bool heightCheck, bool apply, Heightmap ___m_hmap, int ___m_width, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedPaint)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (ClientSideGridModeOverride.IsGridModeEnabled(radius))
		{
			PreciseTerrainModifier.RecolorTerrain(worldPos, paintType, ___m_hmap, ___m_width, ref ___m_paintMask, ref ___m_modifiedPaint);
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
public static class ClientSideGridModeOverride
{
	private static bool Prefix(TerrainOp modifier)
	{
		if (Keybindings.GridModeEnabled)
		{
			if (modifier.m_settings.m_smooth)
			{
				modifier.m_settings.m_smoothRadius = float.NegativeInfinity;
			}
			if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta >= 0f)
			{
				modifier.m_settings.m_raiseRadius = float.NegativeInfinity;
				modifier.m_settings.m_raiseDelta = GroundLevelSpinner.value;
			}
			if (modifier.m_settings.m_paintCleared)
			{
				modifier.m_settings.m_paintRadius = float.NegativeInfinity;
			}
		}
		return true;
	}

	public static bool IsGridModeEnabled(float radius)
	{
		return radius == float.NegativeInfinity;
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("dymek.dev.OCDheim", "OCDheim", "0.1.5")]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class OCDheim : BaseUnityPlugin
{
	private Texture2D brick1x1 => LoadTextureFromDisk("brick_1x1.png");

	private Texture2D brick2x1 => LoadTextureFromDisk("brick_2x1.png");

	private Texture2D brick1x2 => LoadTextureFromDisk("brick_1x2.png");

	private Texture2D brick4x2 => LoadTextureFromDisk("brick_4x2.png");

	private Harmony harmony { get; } = new Harmony("dymek.OCDheim");


	private static OCDheim ocdheim { get; set; }

	public static Texture2D LoadTextureFromDisk(string fileName)
	{
		return AssetUtils.LoadTexture(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)ocdheim).Info.Location), fileName), true);
	}

	public void Awake()
	{
		ocdheim = this;
		harmony.PatchAll();
		PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimToolPieces;
		PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimBuildPieces;
		PrefabManager.OnVanillaPrefabsAvailable += ModVanillaValheimTools;
	}

	private void AddOCDheimToolPieces()
	{
		AddToolPiece<RemoveModificationsOverlayVisualizer>("Remove Terrain Modifications", "mud_road_v2", "Hoe", OverlayVisualizer.remove);
	}

	private void AddToolPiece<TOverlayVisualizer>(string pieceName, string basePieceName, string pieceTable, Texture2D iconTexture, bool level = false, bool raise = false, bool smooth = false, bool paint = false) where TOverlayVisualizer : OverlayVisualizer
	{
		//IL_0020: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Expected O, but got Unknown
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Expected O, but got Unknown
		if (PieceManager.Instance.GetPiece(pieceName) == null)
		{
			Sprite icon = Sprite.Create(new Texture2D(64, 64), new Rect(0f, 0f, 64f, 64f), Vector2.zero);
			if ((Object)(object)iconTexture == (Object)null)
			{
				Debug.LogWarning((object)"OCDHeim: Installation is missing Texture Files.");
			}
			else
			{
				icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero);
			}
			CustomPiece val = new CustomPiece(pieceName, basePieceName, new PieceConfig
			{
				Name = pieceName,
				Icon = icon,
				PieceTable = pieceTable
			});
			Settings settings = val.PiecePrefab.GetComponent<TerrainOp>().m_settings;
			settings.m_level = level;
			settings.m_raise = raise;
			settings.m_smooth = smooth;
			settings.m_paintCleared = paint;
			val.PiecePrefab.AddComponent<TOverlayVisualizer>();
			PieceManager.Instance.AddPiece(val);
		}
	}

	private void AddOCDheimBuildPieces()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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)
		AddBrickBuildPiece("1x1", new Vector3(0.5f, 1f, 0.5f), 3, brick1x1);
		AddBrickBuildPiece("2x1", new Vector3(1f, 1f, 0.5f), 4, brick2x1);
		AddBrickBuildPiece("4x2", new Vector3(2f, 2f, 0.5f), 6, brick4x2);
		AddBrickBuildPiece("1x2", new Vector3(0.5f, 2f, 0.5f), 5, brick1x2);
		PrefabManager.OnVanillaPrefabsAvailable -= AddOCDheimBuildPieces;
	}

	private void AddBrickBuildPiece(string brickSuffix, Vector3 brickScale, int brickPrice, Texture2D iconTexture)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00cc: Expected O, but got Unknown
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Expected O, but got Unknown
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Expected O, but got Unknown
		if (PieceManager.Instance.GetPiece("stone_floor_" + brickSuffix) == null)
		{
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("stone_floor_" + brickSuffix, "stone_floor_2x2");
			Sprite icon = Sprite.Create(new Texture2D(64, 64), new Rect(0f, 0f, 64f, 64f), Vector2.zero);
			if ((Object)(object)iconTexture == (Object)null)
			{
				Debug.LogWarning((object)"OCDHeim: Installation is missing Texture Files.");
			}
			else
			{
				icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero);
			}
			val.transform.localScale = brickScale;
			PieceConfig val2 = new PieceConfig();
			val2.Name = "Smooth stone " + brickSuffix;
			val2.PieceTable = "Hammer";
			val2.Category = "Building";
			val2.Icon = icon;
			val2.AddRequirement(new RequirementConfig("Stone", brickPrice, 0, true));
			PieceManager.Instance.AddPiece(new CustomPiece(val, false, val2));
		}
	}

	private void ModVanillaValheimTools()
	{
		PrefabManager.Instance.GetPrefab("mud_road_v2").AddComponent<LevelGroundOverlayVisualizer>();
		PrefabManager.Instance.GetPrefab("raise_v2").AddComponent<RaiseGroundOverlayVisualizer>();
		PrefabManager.Instance.GetPrefab("path_v2").AddComponent<PaveRoadOverlayVisualizer>();
		PrefabManager.Instance.GetPrefab("paved_road_v2").AddComponent<PaveRoadOverlayVisualizer>();
		PrefabManager.Instance.GetPrefab("cultivate_v2").AddComponent<CultivateOverlayVisualizer>();
		PrefabManager.Instance.GetPrefab("replant_v2").AddComponent<SeedGrassOverlayVisualizer>();
	}
}
public class Circle : ISide
{
	private const int CircleDivisions = 8;

	public char name { get; private set; }

	public Vector3 midSnapNode { get; private set; }

	public Vector2 radial { get; private set; }

	public Circle(Piece piece, Vector2 radial, char name = 'A')
	{
		//IL_0011: 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)
		this.name = name;
		this.radial = radial;
		midSnapNode = piece.TopMiddlee();
	}

	public void FillUp(HashSet<SnapNode> snapNodes)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < 8; i++)
		{
			Vector3 val = Quaternion.Euler(new Vector3(0f, 45f * (float)i, 0f)) * Vector2.op_Implicit(radial);
			Vector3 val2 = midSnapNode + val;
			snapNodes.Add(new SnapNode(midSnapNode, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY));
			snapNodes.Add(new SnapNode(val2, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY));
			SnapNode.RecursiveSplit(midSnapNode, val2, snapNodes);
		}
	}

	public override string ToString()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		return $"Circle {name}: {midSnapNode} + {radial} * quaternion rotation";
	}
}
public interface ISide
{
	void FillUp(HashSet<SnapNode> snapNodes);
}
public struct Line : ISide
{
	public char name { get; private set; }

	public Vector3 minSnapNode { get; private set; }

	public Vector3 maxSnapNode { get; private set; }

	public void FillUp(HashSet<SnapNode> snapNodes)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		SnapNode.RecursiveSplit(minSnapNode, maxSnapNode, snapNodes);
	}

	public Line(char name, Vector3 minSnapNode, Vector3 maxSnapNode)
	{
		//IL_000a: 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)
		this.name = name;
		this.minSnapNode = minSnapNode;
		this.maxSnapNode = maxSnapNode;
	}

	public override string ToString()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		return $"Line {name}: ({minSnapNode}, {maxSnapNode})";
	}
}
public struct SnapNode
{
	public enum Type
	{
		PRIMARY,
		IMPOSED,
		DERIVED
	}

	public enum Precision
	{
		ORDINARY,
		SUPERIOR
	}

	public const float OrdinaryPrecisionSplitThreshold = 1.5f;

	public const float SuperiorPrecisionMultiplier = 2f;

	public Vector3 position { get; private set; }

	public Type type { get; private set; }

	public Precision precision { get; private set; }

	private static bool ShouldSplitInOrdinaryPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return Vector3.Distance(prevSnapNode, nextSnapNode) > 1.5f;
	}

	private static bool ShouldSplitInSuperiorPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return Vector3.Distance(prevSnapNode, nextSnapNode) > 0.75f;
	}

	public SnapNode(Vector3 position, Type type, Precision precision)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		this.position = position;
		this.type = type;
		this.precision = precision;
	}

	public static void RecursiveSplit(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: 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)
		snapNodes.Add(new SnapNode(snapNodeA, Type.PRIMARY, Precision.ORDINARY));
		snapNodes.Add(new SnapNode(snapNodeB, Type.PRIMARY, Precision.ORDINARY));
		RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB, snapNodes);
	}

	private static void RecursiveSplitInOrdinaryPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes, int splitLevel = 0)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//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_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: 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_001e: 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_002e: 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_0038: 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 (ShouldSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB))
		{
			Vector3 val = (snapNodeA + snapNodeB) * 0.5f;
			snapNodes.Add(new SnapNode(val, Type.DERIVED, Precision.ORDINARY));
			RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, val, snapNodes, splitLevel);
			RecursiveSplitInOrdinaryPrecisionMode(val, snapNodeB, snapNodes, splitLevel);
		}
		else
		{
			RecursiveSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB, snapNodes, splitLevel);
		}
	}

	private static void RecursiveSplitInSuperiorPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes, int splitLevel)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: 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_001e: 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_002e: 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_0038: 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 (ShouldSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB))
		{
			Vector3 val = (snapNodeA + snapNodeB) * 0.5f;
			snapNodes.Add(new SnapNode(val, Type.DERIVED, Precision.SUPERIOR));
			RecursiveSplitInSuperiorPrecisionMode(snapNodeA, val, snapNodes, splitLevel);
			RecursiveSplitInSuperiorPrecisionMode(val, snapNodeB, snapNodes, splitLevel);
		}
	}

	public static implicit operator Vector3(SnapNode snapNode)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		return snapNode.position;
	}

	public override string ToString()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		return $"{type} Snap Node of {precision} precision: {position}";
	}

	public override bool Equals(object other)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		return other is SnapNode snapNode && snapNode.position == position;
	}

	public override int GetHashCode()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = position;
		return ((object)(Vector3)(ref val)).GetHashCode();
	}
}
public class SnapTree
{
	public struct TraversalResult
	{
		public Vector3 buildPieceSnapNode { get; }

		public SnapNode neighbourSnapNode { get; }

		public Piece neighbourPiece { get; }

		public TraversalResult(Vector3 buildPieceSnapNode, SnapNode neighbourSnapNode, Piece neighbourPiece)
		{
			//IL_0002: 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)
			this.buildPieceSnapNode = buildPieceSnapNode;
			this.neighbourSnapNode = neighbourSnapNode;
			this.neighbourPiece = neighbourPiece;
		}
	}

	private const int SidesOfLine = 1;

	private const int SidesOfBox = 1;

	private const int SidesOfCube = 6;

	private const int SidesOfOctagon = 10;

	private const float SnapThreshold = 1f;

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

	private static readonly Dictionary<Piece, SnapTree> snapWood = new Dictionary<Piece, SnapTree>(1000);

	private static Func<SnapNode.Precision, bool> ordinaryPrecisionOnly = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY;

	private static Func<SnapNode.Precision, bool> ordinaryAndSuperiorPrecision = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY || precision == SnapNode.Precision.SUPERIOR;

	public Piece piece { get; private set; }

	private HashSet<SnapNode> snapNodes { get; } = new HashSet<SnapNode>();


	private static bool FormValidTwoDimensionalBoxSide(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD)
	{
		//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_0009: 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)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//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_001f: Unknown result type (might be due to invalid IL or missing references)
		return snapNodeA != snapNodeB && snapNodeA != snapNodeC && snapNodeB + snapNodeC - snapNodeA == snapNodeD;
	}

	private static Func<Vector3, Vector3, Vector3, Vector3, bool> FormValidThreeDimensionalBoxSide(Piece piece)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		Vector3 pieceMid = ((Component)piece).transform.position;
		return delegate(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (snapNodeA + snapNodeD) * 0.5f;
			return FormValidTwoDimensionalBoxSide(snapNodeA, snapNodeB, snapNodeC, snapNodeD) && pieceMid != val;
		};
	}

	private static bool LiesOnVerticalMiddle(Vector3 snapNode, Piece piece)
	{
		//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)
		return snapNode.x == ((Component)piece).transform.position.y;
	}

	private static bool LiesOnHorizontalMiddle(Vector3 snapNode, Piece piece)
	{
		//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)
		//IL_0018: 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)
		return snapNode.x == ((Component)piece).transform.position.x && snapNode.z == ((Component)piece).transform.position.z;
	}

	private static bool LiesOnSameVerticalSide(Vector3 snapNodeA, Vector3 snapNodeB)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		return snapNodeA.x == snapNodeB.x && snapNodeA.y != snapNodeB.y && snapNodeA.z == snapNodeB.z;
	}

	private static bool LiesOnSameHorizontalSide(Vector3 snapNodeA, Vector3 snapNodeB)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return snapNodeA.y != snapNodeB.y;
	}

	private SnapTree(Piece piece)
	{
		this.piece = piece;
		List<ISide> list = FindSidesOf(piece);
		foreach (ISide item in list)
		{
			item.FillUp(snapNodes);
		}
	}

	private static SnapTree Of(Piece piece)
	{
		if (snapWood.ContainsKey(piece))
		{
			return snapWood[piece];
		}
		SnapTree snapTree = new SnapTree(piece);
		snapWood[piece] = snapTree;
		return snapTree;
	}

	public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeTo(Vector3 referencePosition, List<Piece> pieces)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return FindNearestSnapNodeTo(referencePosition, pieces, ordinaryPrecisionOnly);
	}

	public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeTo(Vector3 referencePosition, List<Piece> pieces)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return FindNearestSnapNodeTo(referencePosition, pieces, ordinaryAndSuperiorPrecision);
	}

	public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeCombinationOf(Piece buildPiece, List<Piece> neighbourPieces)
	{
		return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodesDefensiveCopy(), neighbourPieces, ordinaryPrecisionOnly);
	}

	public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeCombinationOf(Piece buildPiece, List<Piece> neighbourPieces)
	{
		return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodesDefensiveCopy(), neighbourPieces, ordinaryAndSuperiorPrecision);
	}

	private static List<ISide> FindSidesOf(Piece piece)
	{
		if (piece.IsConstructionPiece())
		{
			if (piece.IsLine())
			{
				return FindSideOfLine(piece);
			}
			if (piece.IsBox())
			{
				return FindSideOfBox(piece);
			}
			if (piece.IsCube())
			{
				return FindSidesOfCube(piece);
			}
			if (piece.IsCylinder())
			{
				return FindSidesOfCylinder(piece);
			}
			return FindSidesOfUndefined(piece);
		}
		if (piece.IsSnappableFurniturePiece())
		{
			return new List<ISide> { PieceHelpers.SnappableFurniturePieces[piece.m_name](piece) };
		}
		return new List<ISide>();
	}

	private static List<ISide> FindSideOfLine(Piece piece)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		List<ISide> list = FindSidesOfUndefined(piece);
		if (list.Count != 1)
		{
			Debug.LogWarning((object)$"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {1}, ACTUAL SIDES: {list.Count}");
		}
		return list;
	}

	private static List<ISide> FindSideOfBox(Piece piece)
	{
		return FindSidesOfBoxOrCube(piece, FormValidTwoDimensionalBoxSide, 1);
	}

	private static List<ISide> FindSidesOfCube(Piece piece)
	{
		return FindSidesOfBoxOrCube(piece, FormValidThreeDimensionalBoxSide(piece), 6);
	}

	private static List<ISide> FindSidesOfBoxOrCube(Piece piece, Func<Vector3, Vector3, Vector3, Vector3, bool> isValidSide, int numberOfSides)
	{
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_006