Decompiled source of Shack Better Paths v1.1.0

ShackBetterPaths.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShackBetterPaths")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("Shack Better Paths")]
[assembly: AssemblyTitle("ShackBetterPaths")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TheShack.BetterPaths
{
	internal static class Access
	{
		public static FieldRef<TerrainComp, ZNetView> TerrainView;

		public static FieldRef<TerrainComp, Heightmap> TerrainMap;

		public static FieldRef<TerrainComp, bool> TerrainInitialized;

		public static FieldRef<TerrainComp, int> TerrainWidth;

		public static FieldRef<TerrainComp, float[]> LevelDelta;

		public static FieldRef<TerrainComp, float[]> SmoothDelta;

		public static FieldRef<TerrainComp, bool[]> ModifiedHeight;

		public static FieldRef<TerrainComp, int> Operations;

		public static FieldRef<TerrainComp, Vector3> LastOpPoint;

		public static FieldRef<TerrainComp, float> LastOpRadius;

		public static FieldRef<TerrainComp, Color[]> PaintMask;

		public static FieldRef<TerrainComp, bool[]> ModifiedPaint;

		public static Action<TerrainComp, bool> Save;

		public static Action<TerrainComp, Vector3, Vector3, Settings> PaintCleared;

		public static Action<TerrainOp> OnPlaced;

		public static FieldRef<Player, GameObject> PlacementGhost;

		public static FieldRef<Player, bool> AltPlace;

		public static Action<Player, bool> UpdatePlacementGhost;

		public static void Init()
		{
			TerrainView = AccessTools.FieldRefAccess<TerrainComp, ZNetView>("m_nview");
			TerrainMap = AccessTools.FieldRefAccess<TerrainComp, Heightmap>("m_hmap");
			TerrainInitialized = AccessTools.FieldRefAccess<TerrainComp, bool>("m_initialized");
			TerrainWidth = AccessTools.FieldRefAccess<TerrainComp, int>("m_width");
			LevelDelta = AccessTools.FieldRefAccess<TerrainComp, float[]>("m_levelDelta");
			SmoothDelta = AccessTools.FieldRefAccess<TerrainComp, float[]>("m_smoothDelta");
			ModifiedHeight = AccessTools.FieldRefAccess<TerrainComp, bool[]>("m_modifiedHeight");
			Operations = AccessTools.FieldRefAccess<TerrainComp, int>("m_operations");
			LastOpPoint = AccessTools.FieldRefAccess<TerrainComp, Vector3>("m_lastOpPoint");
			LastOpRadius = AccessTools.FieldRefAccess<TerrainComp, float>("m_lastOpRadius");
			PaintMask = AccessTools.FieldRefAccess<TerrainComp, Color[]>("m_paintMask");
			ModifiedPaint = AccessTools.FieldRefAccess<TerrainComp, bool[]>("m_modifiedPaint");
			Save = Method<Action<TerrainComp, bool>>(typeof(TerrainComp), "Save", new Type[1] { typeof(bool) });
			PaintCleared = Method<Action<TerrainComp, Vector3, Vector3, Settings>>(typeof(TerrainComp), "PaintCleared", new Type[3]
			{
				typeof(Vector3),
				typeof(Vector3),
				typeof(Settings)
			});
			OnPlaced = Method<Action<TerrainOp>>(typeof(TerrainOp), "OnPlaced", Array.Empty<Type>());
			PlacementGhost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");
			AltPlace = AccessTools.FieldRefAccess<Player, bool>("m_altPlace");
			UpdatePlacementGhost = Method<Action<Player, bool>>(typeof(Player), "UpdatePlacementGhost", new Type[1] { typeof(bool) });
		}

		private static T Method<T>(Type type, string name, params Type[] parameters) where T : Delegate
		{
			return AccessTools.MethodDelegate<T>(AccessTools.Method(type, name, parameters, (Type[])null) ?? throw new MissingMethodException(type.Name, name), (object)null, true);
		}
	}
	internal static class FreeCam
	{
		private const float DetachedDistance = 15f;

		private static FieldInfo magicCamActive;

		private static bool lookedForMagicCam;

		private static bool wasActive;

		private static readonly Dictionary<Tool, Vector3> lastPoint = new Dictionary<Tool, Vector3>();

		public static bool Active(Player player)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!lookedForMagicCam)
			{
				lookedForMagicCam = true;
				Type type = AccessTools.TypeByName("TheShack.MagicCam.Plugin");
				magicCamActive = ((type != null) ? AccessTools.Field(type, "BuildCameraActive") : null);
			}
			if (magicCamActive != null)
			{
				return (bool)magicCamActive.GetValue(null);
			}
			if ((Object)(object)player != (Object)null && (Object)(object)GameCamera.instance != (Object)null)
			{
				return Vector3.Distance(((Component)GameCamera.instance).transform.position, ((Character)player).GetEyePoint()) > 15f;
			}
			return false;
		}

		public static void Track()
		{
			bool flag = (Object)(object)Player.m_localPlayer != (Object)null && Active(Player.m_localPlayer);
			if (flag != wasActive)
			{
				wasActive = flag;
				lastPoint.Clear();
			}
		}

		public static Vector3 StartFor(Tool tool, Vector3 aim, out bool newPath)
		{
			//IL_004a: 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_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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (lastPoint.TryGetValue(tool, out var value))
			{
				Vector2 val = new Vector2(aim.x - value.x, aim.z - value.z);
				if (((Vector2)(ref val)).magnitude <= Settings.MaxDistance.Value)
				{
					newPath = false;
					return value;
				}
			}
			newPath = true;
			return aim;
		}

		public static void Remember(Tool tool, Vector3 end)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			lastPoint[tool] = end;
		}
	}
	internal static class Grading
	{
		private sealed class Ground
		{
			public float[] Heights;

			public float[] LimitBase;
		}

		private const string RpcName = "theshack.betterpaths.Grade";

		private const int DataVersion = 2;

		private const float MaxChange = 8f;

		private const float PaintSpacing = 0.75f;

		private static bool warnedBadStrip;

		private static bool warnedNoPaint;

		private static readonly ConditionalWeakTable<TerrainComp, Ground> grounds = new ConditionalWeakTable<TerrainComp, Ground>();

		public static void RememberGround(TerrainComp comp, List<float> heights, float[] limitBase)
		{
			if (heights != null && limitBase != null && heights.Count == limitBase.Length)
			{
				Ground value = grounds.GetValue(comp, (TerrainComp _) => new Ground());
				if (value.Heights == null || value.Heights.Length != heights.Count)
				{
					value.Heights = new float[heights.Count];
					value.LimitBase = new float[heights.Count];
				}
				heights.CopyTo(value.Heights);
				limitBase.CopyTo(value.LimitBase, 0);
			}
		}

		public static void Send(Strip strip)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			List<Heightmap> list = new List<Heightmap>();
			Heightmap.FindHeightmap(strip.Center, strip.Reach, list);
			strip.Bounds(out var min, out var max);
			foreach (Heightmap item in list)
			{
				float num = (float)item.m_width * item.m_scale * 0.5f;
				Vector3 position = ((Component)item).transform.position;
				if (!(max.x < position.x - num) && !(min.x > position.x + num) && !(max.y < position.z - num) && !(min.y > position.z + num))
				{
					ZNetView val = Access.TerrainView.Invoke(item.GetAndCreateTerrainCompiler());
					if (!((Object)(object)val == (Object)null) && val.IsValid())
					{
						ZPackage val2 = new ZPackage();
						val2.Write(2);
						strip.Write(val2);
						val.InvokeRPC("theshack.betterpaths.Grade", new object[1] { val2 });
					}
				}
			}
		}

		public static void Register(TerrainComp comp)
		{
			ZNetView val = Access.TerrainView.Invoke(comp);
			if ((Object)(object)val != (Object)null)
			{
				val.Register<ZPackage>("theshack.betterpaths.Grade", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg)
				{
					OnGrade(comp, pkg);
				});
			}
		}

		private static void OnGrade(TerrainComp comp, ZPackage pkg)
		{
			if ((Object)(object)comp == (Object)null)
			{
				return;
			}
			ZNetView val = Access.TerrainView.Invoke(comp);
			if (!val.IsValid() || !val.IsOwner() || !Access.TerrainInitialized.Invoke(comp))
			{
				return;
			}
			Strip strip;
			try
			{
				int num = pkg.ReadInt();
				if (num != 2)
				{
					Plugin.Log.LogWarning((object)$"Got a path in format {num}, this version reads {2}; ignored. Everyone needs the same Shack Better Paths.");
					return;
				}
				strip = Strip.Read(pkg);
			}
			catch (Exception)
			{
				Plugin.Log.LogWarning((object)"Ignored a malformed path message.");
				return;
			}
			if (!strip.IsSane())
			{
				if (!warnedBadStrip)
				{
					warnedBadStrip = true;
					Plugin.Log.LogWarning((object)$"Ignored a path outside this server's limits ({strip.Length:0.#} m long, {strip.HalfWidth * 2f:0.#} m wide).");
				}
			}
			else
			{
				Apply(comp, strip);
			}
		}

		private static void Apply(TerrainComp comp, Strip strip)
		{
			//IL_0075: 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_0088: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			Heightmap val = Access.TerrainMap.Invoke(comp);
			int num = Access.TerrainWidth.Invoke(comp);
			int num2 = num + 1;
			float scale = val.m_scale;
			float[] array = Access.LevelDelta.Invoke(comp);
			float[] array2 = Access.SmoothDelta.Invoke(comp);
			bool[] array3 = Access.ModifiedHeight.Invoke(comp);
			if (!grounds.TryGetValue(comp, out var value) || value.Heights.Length != num2 * num2)
			{
				value = null;
			}
			Vector3 position = ((Component)val).transform.position;
			strip.Bounds(out var min, out var max);
			int num3 = default(int);
			int num4 = default(int);
			val.WorldToVertex(new Vector3(min.x, 0f, min.y), ref num3, ref num4);
			int num5 = default(int);
			int num6 = default(int);
			val.WorldToVertex(new Vector3(max.x, 0f, max.y), ref num5, ref num6);
			num3 = Mathf.Max(num3, 0);
			num4 = Mathf.Max(num4, 0);
			num5 = Mathf.Min(num5, num);
			num6 = Mathf.Min(num6, num);
			int num7 = 0;
			for (int i = num4; i <= num6; i++)
			{
				if (strip.PaintOnly)
				{
					break;
				}
				for (int j = num3; j <= num5; j++)
				{
					float x = position.x + ((float)j - (float)num * 0.5f) * scale;
					float z = position.z + ((float)i - (float)num * 0.5f) * scale;
					if (strip.Weight(x, z, out var weight, out var height))
					{
						int num8 = i * num2 + j;
						float num9 = ((value != null) ? value.Heights[num8] : (val.GetHeight(j, i) - array[num8] - array2[num8]));
						float num10 = ((value != null) ? value.LimitBase[num8] : num9);
						float num11 = Mathf.Clamp(Mathf.Lerp(Mathf.Clamp(num9 + array[num8] + array2[num8], num10 - 8f, num10 + 8f), height - position.y, weight), num10 - 8f, num10 + 8f);
						array[num8] = num11 - num9;
						array2[num8] = 0f;
						array3[num8] = true;
						num7++;
					}
				}
			}
			int num12 = 0;
			TerrainOp val2 = default(TerrainOp);
			if (strip.PaintOnly && Settings.PaveOnlyPaths.Value)
			{
				num12 = PaintOverPath(comp, val, strip, Settings.PaintMargin.Value);
			}
			else if (strip.Paint != PaintMode.None && (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.TryGetTerrainOp(strip.PaintPrefabHash, ref val2))
			{
				val.m_doLateUpdate = 1;
				Settings val3 = PaintSettings(val2.m_settings, strip.HalfWidth + Settings.PaintMargin.Value);
				int num13 = ((!strip.IsPad) ? Mathf.CeilToInt(strip.Length / 0.75f) : 0);
				for (int k = 0; k <= num13; k++)
				{
					Vector3 val4 = ((num13 == 0) ? strip.End : Vector3.Lerp(strip.Start, strip.End, (float)k / (float)num13));
					if (val.IsPointInside(val4, val3.m_paintRadius + scale))
					{
						Access.PaintCleared(comp, val4, Vector3.zero, val3);
						num12++;
					}
				}
			}
			else if (strip.Paint != PaintMode.None && !warnedNoPaint)
			{
				warnedNoPaint = true;
				Plugin.Log.LogWarning((object)$"No paint settings for prefab hash {strip.PaintPrefabHash}; paths are graded but not painted.");
			}
			if (num7 != 0 || num12 != 0)
			{
				Access.Operations.Invoke(comp)++;
				Access.LastOpPoint.Invoke(comp) = strip.Center;
				Access.LastOpRadius.Invoke(comp) = strip.Reach;
				Access.Save(comp, arg2: false);
				val.Poke(1, false);
				if ((Object)(object)ClutterSystem.instance != (Object)null)
				{
					ClutterSystem.instance.ResetGrass(strip.Center, strip.Reach);
				}
			}
		}

		private static int PaintOverPath(TerrainComp comp, Heightmap map, Strip strip, float margin)
		{
			//IL_003b: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = Access.PaintMask.Invoke(comp);
			bool[] array2 = Access.ModifiedPaint.Invoke(comp);
			int num = Access.TerrainWidth.Invoke(comp) + 1;
			int num2 = num / 2;
			float scale = map.m_scale;
			Vector3 position = ((Component)map).transform.position;
			float num3 = strip.HalfWidth + margin;
			Color paintMaskPaved = Heightmap.m_paintMaskPaved;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(strip.IsPad ? strip.End.x : strip.Start.x, strip.IsPad ? strip.End.z : strip.Start.z);
			Vector2 val2 = new Vector2(strip.End.x, strip.End.z) - val;
			float sqrMagnitude = ((Vector2)(ref val2)).sqrMagnitude;
			int num4 = 0;
			Vector2 val3 = default(Vector2);
			Color val5 = default(Color);
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num; j++)
				{
					int num5 = i * num + j;
					if (num5 >= array.Length)
					{
						continue;
					}
					((Vector2)(ref val3))..ctor(position.x + ((float)(j - num2) + 0.5f) * scale, position.z + ((float)(i - num2) + 0.5f) * scale);
					float num6 = ((sqrMagnitude > 1E-06f) ? Mathf.Clamp01(Vector2.Dot(val3 - val, val2) / sqrMagnitude) : 0f);
					float num7 = Vector2.Distance(val3, val + val2 * num6);
					if (num7 > num3)
					{
						continue;
					}
					Color val4 = array[num5];
					if (!(Mathf.Max(val4.r, val4.b) <= 0.5f))
					{
						float num8 = Mathf.Pow(1f - num7 / num3, 0.1f);
						((Color)(ref val5))..ctor(Mathf.Lerp(val4.r, paintMaskPaved.r, num8), Mathf.Lerp(val4.g, paintMaskPaved.g, num8), Mathf.Lerp(val4.b, paintMaskPaved.b, num8), val4.a);
						if (val5 != val4)
						{
							array[num5] = val5;
							array2[num5] = true;
							num4++;
						}
					}
				}
			}
			return num4;
		}

		private static Settings PaintSettings(Settings vanilla, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0071: Expected O, but got Unknown
			return new Settings
			{
				m_paintCleared = true,
				m_paintType = vanilla.m_paintType,
				m_paintRadius = radius,
				m_paintStrength = 1f,
				m_paintExp = 0.1f,
				m_paintCurve = null,
				m_paintHeightCheck = false,
				m_addMedianMax = 0f,
				m_centerMultiplicationFactor = 0f,
				m_pointMultiplicationFactor = 0f,
				m_halfOffset = vanilla.m_halfOffset
			};
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		private static Strip? Pending;

		private static bool pendingFromCamera;

		private static bool pendingNewPath;

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		[HarmonyPrefix]
		private static bool TryPlacePiecePrefix(Player __instance, Piece piece, ref bool __result)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			Pending = null;
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)piece == (Object)null)
			{
				return true;
			}
			Tool tool = Tools.Of(((Component)piece).gameObject);
			bool flag = Tools.AltPlaceHeld(__instance);
			if (!Tools.Handles(tool) || (flag && !Tools.PaintOnly(tool)))
			{
				return true;
			}
			Access.UpdatePlacementGhost(__instance, arg2: false);
			GameObject val = Access.PlacementGhost.Invoke(__instance);
			if ((Object)(object)val == (Object)null || !val.activeSelf)
			{
				return true;
			}
			Vector3 position = val.transform.position;
			bool flag2 = !flag && FreeCam.Active(__instance);
			bool newPath = false;
			string error = null;
			bool flag3 = true;
			Strip strip;
			if (flag)
			{
				strip = Strip.Make(__instance, position, position, tool);
			}
			else if (flag2)
			{
				strip = Strip.Make(__instance, FreeCam.StartFor(tool, position, out newPath), position, tool);
			}
			else
			{
				flag3 = Strip.TryFromFeet(__instance, position, tool, out strip, out error);
			}
			if (!flag3 || !CheckArea(strip, out error) || !CheckCost(__instance, piece, ref strip, out error))
			{
				((Character)__instance).Message((MessageType)2, error, 0, (Sprite)null, false);
				__result = false;
				return false;
			}
			Pending = strip;
			pendingFromCamera = flag2;
			pendingNewPath = newPath;
			return true;
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		[HarmonyPostfix]
		private static void TryPlacePiecePostfix()
		{
			Pending = null;
		}

		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		[HarmonyPrefix]
		private static bool TerrainOpAwakePrefix(TerrainOp __instance)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (TerrainOp.m_forceDisableTerrainOps || !Pending.HasValue)
			{
				return true;
			}
			Strip value = Pending.Value;
			Pending = null;
			if (Tools.Of(((Component)__instance).gameObject) != value.Tool)
			{
				return true;
			}
			Grading.Send(value);
			if (pendingFromCamera)
			{
				FreeCam.Remember(value.Tool, value.End);
				if (pendingNewPath && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)1, $"New path: clicks within {Settings.MaxDistance.Value:0} m connect", 0, (Sprite)null, false);
				}
			}
			Player localPlayer = Player.m_localPlayer;
			Piece component = ((Component)__instance).GetComponent<Piece>();
			if (value.CostMultiplier > 1 && (Object)(object)localPlayer != (Object)null && (Object)(object)component != (Object)null && !IsFree(localPlayer, component))
			{
				localPlayer.ConsumeResources(component.m_resources, 0, -1, value.CostMultiplier - 1);
			}
			Access.OnPlaced(__instance);
			Object.Destroy((Object)(object)((Component)__instance).gameObject);
			return false;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		[HarmonyPostfix]
		private static void UpdatePlacementGhostPostfix(Player __instance)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			GameObject val = Access.PlacementGhost.Invoke(__instance);
			if (!((Object)(object)val == (Object)null) && val.activeSelf && Tools.Of(val) == Tool.PavedRoad && Tools.Handles(Tool.PavedRoad))
			{
				Vector3 position = val.transform.position;
				float num = default(float);
				if (ZoneSystem.instance.GetGroundHeight(position, ref num))
				{
					val.transform.position = new Vector3(position.x, num, position.z);
				}
			}
		}

		[HarmonyPatch(typeof(TerrainComp), "Awake")]
		[HarmonyPostfix]
		private static void TerrainCompAwakePostfix(TerrainComp __instance)
		{
			Grading.Register(__instance);
		}

		[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
		[HarmonyPrefix]
		private static void ApplyToHeightmapPrefix(TerrainComp __instance, List<float> heights, float[] baseHeights)
		{
			Grading.RememberGround(__instance, heights, baseHeights);
		}

		private static bool CheckArea(Strip strip, out string error)
		{
			//IL_001b: 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_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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			error = null;
			int num = Mathf.Max(1, Mathf.CeilToInt(strip.Length));
			for (int i = 0; i <= num; i++)
			{
				Vector3 val = Vector3.Lerp(strip.Start, strip.End, (float)i / (float)num);
				if (!PrivateArea.CheckAccess(val, strip.HalfWidth + strip.Blend, true, false))
				{
					error = "$msg_privatezone";
					return false;
				}
				if (Location.IsInsideNoBuildLocation(val))
				{
					error = "$msg_nobuildzone";
					return false;
				}
			}
			return true;
		}

		private static bool CheckCost(Player player, Piece piece, ref Strip strip, out string error)
		{
			//IL_0091: 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_00a4: 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_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)
			error = null;
			float value = Settings.MetersPerStone.Value;
			if (strip.Tool != Tool.PavedRoad || value <= 0f || strip.IsPad)
			{
				return true;
			}
			int num = Mathf.Max(1, Mathf.CeilToInt((strip.Length - 0.05f) / value));
			if (num == 1 || IsFree(player, piece))
			{
				strip.CostMultiplier = num;
				return true;
			}
			int num2 = num;
			while (num2 > 1 && !HaveTimes(player, piece, num2))
			{
				num2--;
			}
			strip.CostMultiplier = num2;
			if (num2 < num)
			{
				float length = strip.Length;
				float num3 = Mathf.Min(length, (float)num2 * value);
				Vector3 direction = strip.Direction;
				strip.End = new Vector3(strip.Start.x + direction.x * num3, strip.End.y, strip.Start.z + direction.z * num3);
				((Character)player).Message((MessageType)1, "Out of " + Localization.instance.Localize(piece.m_resources[0].m_resItem.m_itemData.m_shared.m_name) + ": " + $"paved {num3:0.#} of {length:0.#} m", 0, (Sprite)null, false);
			}
			return true;
		}

		private static bool HaveTimes(Player player, Piece piece, int times)
		{
			int[] array = new int[piece.m_resources.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = piece.m_resources[i].m_amount;
			}
			try
			{
				Requirement[] resources = piece.m_resources;
				foreach (Requirement obj in resources)
				{
					obj.m_amount *= times;
				}
				return player.HaveRequirements(piece, (RequirementMode)0);
			}
			finally
			{
				for (int k = 0; k < array.Length; k++)
				{
					piece.m_resources[k].m_amount = array[k];
				}
			}
		}

		private static bool IsFree(Player player, Piece piece)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!player.NoCostCheat())
			{
				return ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey());
			}
			return true;
		}
	}
	[BepInPlugin("theshack.betterpaths", "Shack Better Paths", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "theshack.betterpaths";

		public const string PluginName = "Shack Better Paths";

		public const string PluginVersion = "1.1.0";

		internal static ManualLogSource Log;

		private bool ready;

		private void Update()
		{
			if (ready)
			{
				FreeCam.Track();
			}
		}

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings.Bind(((BaseUnityPlugin)this).Config);
			Harmony val = new Harmony("theshack.betterpaths");
			try
			{
				Access.Init();
				val.PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception arg)
			{
				val.UnpatchSelf();
				Log.LogError((object)string.Format("{0} could not hook into this game version; the hoe stays vanilla. {1}", "Shack Better Paths", arg));
				return;
			}
			ready = true;
			Log.LogInfo((object)(string.Format("{0} {1} ready (path width {2} m, ", "Shack Better Paths", "1.1.0", Settings.Width.Value) + $"Paved road: 1 stone per {Settings.MetersPerStone.Value} m)."));
		}
	}
	internal static class Settings
	{
		public static ConfigEntry<bool> PathenGrades;

		public static ConfigEntry<bool> PavedRoadPaints;

		public static ConfigEntry<bool> PaveOnlyPaths;

		public static ConfigEntry<float> Width;

		public static ConfigEntry<float> EdgeBlend;

		public static ConfigEntry<float> MaxDistance;

		public static ConfigEntry<float> PaintMargin;

		public static ConfigEntry<float> MetersPerStone;

		public static void Bind(ConfigFile config)
		{
			int order = 100;
			PathenGrades = Bind<bool>("1 - Tools", "Pathen grades", value: true, "Pathen grades an even slope from your feet to where you aim (in the build camera: from your last click), then paints it dirt. Off: vanilla Pathen. Holding Shift gives vanilla Pathen either way (paints dirt only).");
			PavedRoadPaints = Bind<bool>("1 - Tools", "Paved road paints", value: true, "Paved road only paints stone over the ground, never changing its height: along a strip from your feet to where you aim (in the build camera: from your last click). Shift paints a round patch where you aim. Off: vanilla Paved road (smooths the ground toward the height of your feet).");
			PaveOnlyPaths = Bind<bool>("1 - Tools", "Paved road only on paths", value: true, "Paved road lays stone only where the ground is already dirt or paved (a path), so a click that spills onto grass leaves the grass alone. Off: it paves the whole strip.");
			Width = Bind<float>("2 - Shape", "Path width", 4f, "Width of the flat part of the path, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f));
			EdgeBlend = Bind<float>("2 - Shape", "Edge blend", 1.5f, "How far past the sides and the far end the path blends into the ground around it, in meters. 0 = hard edges.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f));
			PaintMargin = Bind<float>("2 - Shape", "Paint margin", 0.25f, "How far past each side of the path the dirt or paving goes, in meters, so the edges come out clean. The banks beyond keep their grass.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f));
			MaxDistance = Bind<float>("2 - Shape", "Max distance from feet", 8f, "Longest strip, in meters. Walking: a click further than this from your feet is refused. In the build camera: a click further than this from your last click starts a new path.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f));
			MetersPerStone = Bind<float>("3 - Cost", "Paved road meters per stone", 2f, "Paved road takes its stone once per this many meters of path, rounded up (vanilla takes 1 stone per click). 0 = once per click, like vanilla. Pathen is free, like vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f));
			ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null)
			{
				//IL_0015: 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_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Expected O, but got Unknown
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				return config.Bind<T>(section, key, value, new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true,
					Order = order--
				} }));
			}
		}
	}
	internal struct Strip
	{
		public const float MinLength = 0.5f;

		public Vector3 Start;

		public Vector3 End;

		public float HalfWidth;

		public float Blend;

		public PaintMode Paint;

		public int PaintPrefabHash;

		public bool PaintOnly;

		public Tool Tool;

		public int CostMultiplier;

		public float Length
		{
			get
			{
				//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)
				Vector2 val = new Vector2(End.x - Start.x, End.z - Start.z);
				return ((Vector2)(ref val)).magnitude;
			}
		}

		public bool IsPad => Length < 0.5f;

		public Vector3 Center
		{
			get
			{
				//IL_0025: 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_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_001e: Unknown result type (might be due to invalid IL or missing references)
				if (!IsPad)
				{
					return (Start + End) * 0.5f;
				}
				return End;
			}
		}

		public float Reach => (IsPad ? 0f : (Length * 0.5f)) + HalfWidth + Blend;

		public Vector3 Direction
		{
			get
			{
				//IL_0050: 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)
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(End.x - Start.x, 0f, End.z - Start.z);
				if (!(((Vector3)(ref val)).sqrMagnitude > 1E-06f))
				{
					return Vector3.forward;
				}
				return ((Vector3)(ref val)).normalized;
			}
		}

		public void Bounds(out Vector2 min, out Vector2 max)
		{
			//IL_001f: 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_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_003e: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			float num = HalfWidth + Blend;
			Vector3 val = (IsPad ? End : Start);
			min = new Vector2(Mathf.Min(val.x, End.x) - num, Mathf.Min(val.z, End.z) - num);
			max = new Vector2(Mathf.Max(val.x, End.x) + num, Mathf.Max(val.z, End.z) + num);
		}

		public bool Weight(float x, float z, out float weight, out float height)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			float num;
			float num2;
			if (IsPad)
			{
				Vector2 val = new Vector2(x - End.x, z - End.z);
				num = ((Vector2)(ref val)).magnitude - HalfWidth;
				num2 = 1f;
			}
			else
			{
				float length = Length;
				Vector3 direction = Direction;
				float num3 = x - Start.x;
				float num4 = z - Start.z;
				float num5 = num3 * direction.x + num4 * direction.z;
				if (num5 < 0f)
				{
					weight = 0f;
					height = 0f;
					return false;
				}
				float num6 = Mathf.Max(0f, Mathf.Abs(num3 * direction.z - num4 * direction.x) - HalfWidth);
				float num7 = num5 - length;
				num = ((num7 > 0f) ? Mathf.Sqrt(num7 * num7 + num6 * num6) : num6);
				num2 = Mathf.Clamp01(num5 / length);
			}
			height = Mathf.Lerp(Start.y, End.y, num2);
			if (num <= 0f)
			{
				weight = 1f;
				return true;
			}
			if (num >= Blend)
			{
				weight = 0f;
				return false;
			}
			float num8 = num / Blend;
			weight = 1f - num8 * num8 * (3f - 2f * num8);
			return true;
		}

		public void Write(ZPackage pkg)
		{
			//IL_0002: 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)
			pkg.Write(Start);
			pkg.Write(End);
			pkg.Write(HalfWidth);
			pkg.Write(Blend);
			pkg.Write((int)Paint);
			pkg.Write(PaintPrefabHash);
			pkg.Write(PaintOnly);
		}

		public static Strip Read(ZPackage pkg)
		{
			//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_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)
			return new Strip
			{
				Start = pkg.ReadVector3(),
				End = pkg.ReadVector3(),
				HalfWidth = pkg.ReadSingle(),
				Blend = pkg.ReadSingle(),
				Paint = (PaintMode)pkg.ReadInt(),
				PaintPrefabHash = pkg.ReadInt(),
				PaintOnly = pkg.ReadBool()
			};
		}

		public bool IsSane()
		{
			//IL_0001: 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)
			if (Finite(Start) && Finite(End) && HalfWidth > 0f && HalfWidth <= 5f && Blend >= 0f && Blend <= 5f && Length <= Settings.MaxDistance.Value + 1f && (!PaintOnly || Paint != PaintMode.None))
			{
				if (Paint != PaintMode.None)
				{
					if (Paint != PaintMode.Dirt)
					{
						if (Paint == PaintMode.Paved)
						{
							return PaintPrefabHash == StringExtensionMethods.GetStableHashCode("paved_road_v2");
						}
						return false;
					}
					return PaintPrefabHash == StringExtensionMethods.GetStableHashCode("path_v2");
				}
				return PaintPrefabHash == 0;
			}
			return false;
		}

		private static bool Finite(Vector3 v)
		{
			//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_000d: 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_0021: 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)
			if (!float.IsNaN(v.x + v.y + v.z))
			{
				return !float.IsInfinity(v.x + v.y + v.z);
			}
			return false;
		}

		public static bool TryFromFeet(Player player, Vector3 aim, Tool tool, out Strip strip, out string error)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			strip = default(Strip);
			error = null;
			Vector3 position = ((Component)player).transform.position;
			Vector2 val = new Vector2(aim.x - position.x, aim.z - position.z);
			float magnitude = ((Vector2)(ref val)).magnitude;
			if (magnitude > Settings.MaxDistance.Value)
			{
				error = $"Too far from your feet ({magnitude:0} m, max {Settings.MaxDistance.Value:0} m). " + "Stand closer, or use the build camera.";
				return false;
			}
			strip = Make(player, position, aim, tool);
			return true;
		}

		public static Strip Make(Player player, Vector3 start, Vector3 aim, Tool tool)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			Strip result = new Strip
			{
				Start = start,
				End = aim,
				HalfWidth = Settings.Width.Value * 0.5f,
				Blend = Settings.EdgeBlend.Value,
				Paint = Tools.Paint(tool),
				PaintPrefabHash = Tools.PaintPrefabHash(tool),
				PaintOnly = Tools.PaintOnly(tool),
				Tool = tool,
				CostMultiplier = 1
			};
			Vector3 val = result.Direction;
			if (result.IsPad)
			{
				val = ((Component)player).transform.forward;
				val.y = 0f;
				val = ((((Vector3)(ref val)).sqrMagnitude > 1E-06f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			}
			Vector3 side = default(Vector3);
			((Vector3)(ref side))..ctor(val.z, 0f, 0f - val.x);
			result.Start.y = GroundAcross(start, side, result.HalfWidth);
			result.End.y = (result.IsPad ? result.Start.y : GroundAcross(aim, side, result.HalfWidth));
			return result;
		}

		private static float GroundAcross(Vector3 center, Vector3 side, float halfWidth)
		{
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			int num2 = 0;
			float num3 = default(float);
			for (int i = -2; i <= 2; i++)
			{
				if (ZoneSystem.instance.GetGroundHeight(center + side * (halfWidth * (float)i * 0.5f), ref num3))
				{
					num += num3;
					num2++;
				}
			}
			if (num2 <= 0)
			{
				return center.y;
			}
			return num / (float)num2;
		}
	}
	internal enum Tool
	{
		None,
		Pathen,
		PavedRoad
	}
	internal enum PaintMode
	{
		None,
		Dirt,
		Paved
	}
	internal static class Tools
	{
		public const string PathenPrefab = "path_v2";

		public const string PavedRoadPrefab = "paved_road_v2";

		public static Tool Of(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return Tool.None;
			}
			string prefabName = Utils.GetPrefabName(go);
			if (!(prefabName == "path_v2"))
			{
				if (prefabName == "paved_road_v2")
				{
					return Tool.PavedRoad;
				}
				return Tool.None;
			}
			return Tool.Pathen;
		}

		public static bool Handles(Tool tool)
		{
			return tool switch
			{
				Tool.Pathen => Settings.PathenGrades.Value, 
				Tool.PavedRoad => Settings.PavedRoadPaints.Value, 
				_ => false, 
			};
		}

		public static bool PaintOnly(Tool tool)
		{
			return tool == Tool.PavedRoad;
		}

		public static PaintMode Paint(Tool tool)
		{
			return tool switch
			{
				Tool.Pathen => PaintMode.Dirt, 
				Tool.PavedRoad => PaintMode.Paved, 
				_ => PaintMode.None, 
			};
		}

		public static int PaintPrefabHash(Tool tool)
		{
			return Paint(tool) switch
			{
				PaintMode.Dirt => StringExtensionMethods.GetStableHashCode("path_v2"), 
				PaintMode.Paved => StringExtensionMethods.GetStableHashCode("paved_road_v2"), 
				_ => 0, 
			};
		}

		public static bool AltPlaceHeld(Player player)
		{
			if (ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive())
			{
				return Access.AltPlace.Invoke(player);
			}
			if (!ZInput.GetButton("AltPlace"))
			{
				if (ZInput.GetButton("JoyAltPlace"))
				{
					return !ZInput.GetButton("JoyRotate");
				}
				return false;
			}
			return true;
		}
	}
}