Decompiled source of AdvancedTerrainModifiers v1.5.2

TerrainTools.dll

Decompiled 3 hours ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using TerrainTools.Core;
using TerrainTools.Extensions;
using TerrainTools.Patches;
using TerrainTools.Tools;
using TerrainTools.Visualization;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("TerrainTools")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TerrainTools")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.5.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace TerrainTools
{
	[BepInPlugin("Searica.Valheim.TerrainTools", "AdvancedTerrainModifiers", "1.5.2")]
	[BepInDependency("com.jotunn.jotunn", "2.30.1")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal sealed class TerrainTools : BaseUnityPlugin
	{
		internal const string Author = "Searica";

		public const string PluginName = "AdvancedTerrainModifiers";

		public const string PluginGUID = "Searica.Valheim.TerrainTools";

		public const string PluginVersion = "1.5.2";

		public static TerrainTools Instance;

		private static ConfigFileWatcher ConfigFileWatcher;

		private const string MainSection = "Global";

		private const string RadiusSection = "Radius";

		private const string SharpnessSection = "Sharpness";

		private const string ShovelSection = "Shovel";

		private const string HoeSection = "Hoe";

		private const string CultivatorSection = "Cultivator";

		internal bool UpdatePlugin;

		private ConfigEntry<bool> hoverInfoEnabled;

		private readonly Dictionary<string, ConfigEntry<bool>> ToolConfigEntries = new Dictionary<string, ConfigEntry<bool>>();

		private ConfigEntry<bool> enableRadiusModifier;

		private ConfigEntry<KeyCode> radiusModKey;

		private ConfigEntry<float> radiusScrollScale;

		private ConfigEntry<float> maxRadius;

		private ConfigEntry<bool> enableSharpnessModifier;

		private ConfigEntry<KeyCode> hardnessModKey;

		private ConfigEntry<float> hardnessScrollScale;

		private ConfigEntry<bool> enableShovel;

		internal bool IsHoverInforEnabled => hoverInfoEnabled.Value;

		internal bool IsEnableRadiusModifier => enableRadiusModifier.Value;

		internal float MaxRadius => maxRadius.Value;

		internal KeyCode RadiusKey => radiusModKey.Value;

		internal float RadiusScrollScale => radiusScrollScale.Value;

		internal bool IsEnableSharpnessModifier => enableSharpnessModifier.Value;

		internal KeyCode SharpnessKey => hardnessModKey.Value;

		internal float SharpnessScrollScale => hardnessScrollScale.Value;

		internal bool IsShovelEnabled => enableShovel.Value;

		private static string GetSectionName(string pieceTable)
		{
			if (pieceTable == PieceTables.Hoe)
			{
				return "Hoe";
			}
			if (pieceTable == PieceTables.Cultivator)
			{
				return "Cultivator";
			}
			if (pieceTable == "_ShovelPieceTable")
			{
				return "Shovel";
			}
			return "Global";
		}

		internal bool IsToolEnabled(string toolName)
		{
			if (ToolConfigEntries.TryGetValue(toolName, out var value))
			{
				return value?.Value ?? false;
			}
			return false;
		}

		public void Awake()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Config.DisableSaveOnConfigSet();
			SetUpConfigEntries();
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.TerrainTools");
			Game.isModded = true;
			PrefabManager.OnVanillaPrefabsAvailable += Shovel.CreateShovel;
			PieceManager.OnPiecesRegistered += InitManager.InitToolPieces;
			_ = GUIManager.Instance;
			ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			ConfigFileWatcher.OnConfigFileReloaded += delegate
			{
				if (UpdatePlugin)
				{
					InitManager.UpdatePlugin();
					UpdatePlugin = false;
				}
			};
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
				if (UpdatePlugin)
				{
					InitManager.UpdatePlugin();
				}
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				if (UpdatePlugin)
				{
					InitManager.UpdatePlugin();
					UpdatePlugin = false;
				}
			};
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		internal void SetUpConfigEntries()
		{
			Log.Verbosity = ConfigFileExtensions.BindConfigInOrder<Log.InfoLevel>(((BaseUnityPlugin)this).Config, "Global", "Verbosity", Log.InfoLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow Down your game.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			hoverInfoEnabled = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Global", "HoverInfo", true, "Set to true/enabled to show terrain height when using square terrain tools.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			enableRadiusModifier = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Radius", "Radius Modifier", true, "Set to true/enabled to allow modifying the radius of terrain tools using the scroll wheel. Note: Radius cannot be changed on square terraforming tools.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			radiusModKey = ConfigFileExtensions.BindConfigInOrder<KeyCode>(((BaseUnityPlugin)this).Config, "Radius", "Adjust Radius Key", (KeyCode)308, "Modifier key that must be held down when using scroll wheel to change the radius of terrain tools.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			radiusScrollScale = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Radius", "Radius Scroll Speed", 0.1f, "How much each tick of movement from the scroll wheel will change radius size. Larger magnitude means the radius will faster. Negative numbers will reverse the scroll direction to adjust the radius.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			maxRadius = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Radius", "Max Radius", 10f, "Maximum radius of terrain tools.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 20f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			enableSharpnessModifier = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Sharpness", "Sharpness Modifier", true, "Set to true/enabled to allow modifying the hardness of terrain tools using the scroll wheel. Note: Sharpness cannot be changed on square terraforming tools and tools that do not alter ground height do not have a hardness.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			hardnessModKey = ConfigFileExtensions.BindConfigInOrder<KeyCode>(((BaseUnityPlugin)this).Config, "Sharpness", "Adjust Sharpness Key", (KeyCode)306, "Modifier key that must be held down when using scroll wheel to change the hardness of terrain tools.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			hardnessScrollScale = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Sharpness", "Sharpness Scroll Speed", 0.1f, "How much each tick of movement from the scroll wheel will change sharpness. Larger magnitude means the sharpness will faster. Negative numbers will reverse the scroll direction to adjust the sharpness.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			enableShovel = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Shovel", "Shovel", true, "Whether the shovel is craftable in-game. If Enabled then crafting is allowed. If Disabled then crafting new shovels is prevented but existing shovels are untouched.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			enableShovel.SettingChanged += SetUpdatePlugin;
			foreach (string key in ToolConfigs.ToolConfigsMap.Keys)
			{
				ToolDB toolDB = ToolConfigs.ToolConfigsMap[key];
				ConfigEntry<bool> val = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, GetSectionName(toolDB.pieceTable), key, true, "Set to true/enabled to add this terrain tool. Set to false/disabled to remove it.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
				val.SettingChanged += SetUpdatePlugin;
				ToolConfigEntries.Add(key, val);
			}
		}

		private void SetUpdatePlugin(object obj, EventArgs e)
		{
			UpdatePlugin = !UpdatePlugin || UpdatePlugin;
		}
	}
}
namespace TerrainTools.Visualization
{
	public class HoverInfo
	{
		private readonly GameObject _gameObject;

		private readonly Transform _transform;

		private readonly TextMesh _textMesh;

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

		public bool Enabled
		{
			get
			{
				return _gameObject.activeSelf;
			}
			set
			{
				_gameObject.SetActive(value);
			}
		}

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

		public HoverInfo(Transform parentTransform)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			_gameObject = new GameObject();
			_gameObject.transform.parent = parentTransform;
			_transform = _gameObject.transform;
			_textMesh = _gameObject.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_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_0030: 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_0046: 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);
		}
	}
	internal static class IconCache
	{
		private static Texture2D _remove;

		private static Texture2D _cross;

		private static Texture2D _undo;

		private static Texture2D _redo;

		private static Texture2D _box;

		private static Texture2D _pavedRoadSquare;

		private static Texture2D _pavedRoadPath;

		private static Texture2D _pavedRoadPathSquare;

		private static Texture2D _mudRoadSquare;

		private static Texture2D _mudRoadPathSquare;

		private static Texture2D _replantSquare;

		private static Texture2D _cultivateSquare;

		private static Texture2D _cultivatePath;

		private static Texture2D _cultivatePathSquare;

		private static Texture2D _raiseSquare;

		private static Texture2D _lower;

		private static Texture2D _shovel;

		private static readonly MethodInfo LoadImageMethod = AccessTools.Method(typeof(ImageConversion), "LoadImage", new Type[2]
		{
			typeof(Texture2D),
			typeof(byte[])
		}, (Type[])null);

		internal static Texture2D Shovel
		{
			get
			{
				if ((Object)(object)_shovel == (Object)null)
				{
					_shovel = LoadTextureFromResources("ShovelIcon.png");
				}
				return _shovel;
			}
		}

		internal static Texture2D Lower
		{
			get
			{
				if ((Object)(object)_lower == (Object)null)
				{
					_lower = LoadTextureFromResources("lower_v2.png");
				}
				return _lower;
			}
		}

		internal static Texture2D CultivateSquare
		{
			get
			{
				if ((Object)(object)_cultivateSquare == (Object)null)
				{
					_cultivateSquare = LoadTextureFromResources("cultivate_v2_square.png");
				}
				return _cultivateSquare;
			}
		}

		internal static Texture2D CultivatePathSquare
		{
			get
			{
				if ((Object)(object)_cultivatePathSquare == (Object)null)
				{
					_cultivatePathSquare = LoadTextureFromResources("cultivate_v2_path_square.png");
				}
				return _cultivatePathSquare;
			}
		}

		internal static Texture2D CultivatePath
		{
			get
			{
				if ((Object)(object)_cultivatePath == (Object)null)
				{
					_cultivatePath = LoadTextureFromResources("cultivate_v2_path.png");
				}
				return _cultivatePath;
			}
		}

		internal static Texture2D ReplantSquare
		{
			get
			{
				if ((Object)(object)_replantSquare == (Object)null)
				{
					_replantSquare = LoadTextureFromResources("replant_v2_square.png");
				}
				return _replantSquare;
			}
		}

		internal static Texture2D RaiseSquare
		{
			get
			{
				if ((Object)(object)_raiseSquare == (Object)null)
				{
					_raiseSquare = LoadTextureFromResources("raise_v2_square.png");
				}
				return _raiseSquare;
			}
		}

		internal static Texture2D MudRoadPathSquare
		{
			get
			{
				if ((Object)(object)_mudRoadPathSquare == (Object)null)
				{
					_mudRoadPathSquare = LoadTextureFromResources("path_v2_square.png");
				}
				return _mudRoadPathSquare;
			}
		}

		internal static Texture2D MudRoadSquare
		{
			get
			{
				if ((Object)(object)_mudRoadSquare == (Object)null)
				{
					_mudRoadSquare = LoadTextureFromResources("mud_road_v2_square.png");
				}
				return _mudRoadSquare;
			}
		}

		internal static Texture2D PavedRoadPath
		{
			get
			{
				if ((Object)(object)_pavedRoadPath == (Object)null)
				{
					_pavedRoadPath = LoadTextureFromResources("paved_road_v2_path.png");
				}
				return _pavedRoadPath;
			}
		}

		internal static Texture2D PavedRoadPathSquare
		{
			get
			{
				if ((Object)(object)_pavedRoadPathSquare == (Object)null)
				{
					_pavedRoadPathSquare = LoadTextureFromResources("paved_road_v2_path_square.png");
				}
				return _pavedRoadPathSquare;
			}
		}

		internal static Texture2D PavedRoadSquare
		{
			get
			{
				if ((Object)(object)_pavedRoadSquare == (Object)null)
				{
					_pavedRoadSquare = LoadTextureFromResources("paved_road_v2_square.png");
				}
				return _pavedRoadSquare;
			}
		}

		internal static Texture2D Remove
		{
			get
			{
				if ((Object)(object)_remove == (Object)null)
				{
					_remove = LoadTextureFromResources("remove.png");
				}
				return _remove;
			}
		}

		internal static Texture2D Cross
		{
			get
			{
				if ((Object)(object)_cross == (Object)null)
				{
					_cross = LoadTextureFromResources("cross.png");
				}
				return _cross;
			}
		}

		internal static Texture2D Undo
		{
			get
			{
				if ((Object)(object)_undo == (Object)null)
				{
					_undo = LoadTextureFromResources("undo.png");
				}
				return _undo;
			}
		}

		internal static Texture2D Redo
		{
			get
			{
				if ((Object)(object)_redo == (Object)null)
				{
					_redo = LoadTextureFromResources("redo.png");
				}
				return _redo;
			}
		}

		internal static Texture2D Box
		{
			get
			{
				if ((Object)(object)_box == (Object)null)
				{
					_box = LoadTextureFromResources("box.png");
				}
				return _box;
			}
		}

		internal static Sprite LoadEmbeddedTextureAsSprite(string fileName)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTextureFromResources(fileName);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			float num = 100f;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val2, num);
		}

		internal static Texture2D LoadTextureFromResources(string fileName)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			string text = Path.GetExtension(fileName).ToLower();
			if (text != ".png" && text != ".jpg")
			{
				Log.LogWarning("LoadTextureFromResources can only load png or jpg textures");
				return null;
			}
			fileName = Path.GetFileNameWithoutExtension(fileName);
			string name = (from text2 in Assembly.GetExecutingAssembly().GetManifestResourceNames()
				where text2.Contains(fileName)
				select text2).FirstOrDefault();
			Stream? manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
			byte[] array = new byte[manifestResourceStream.Length];
			manifestResourceStream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(0, 0);
			LoadImageMethod.Invoke(null, new object[2] { val, array });
			return val;
		}
	}
	public class Overlay
	{
		private GameObject GameObject { get; }

		private Particle[] Particles => (Particle[])(object)new Particle[2];

		private Transform Transform { get; }

		public ParticleSystem ps { get; }

		public ParticleSystemRenderer psr { get; }

		public MainModule psm { get; }

		public bool Enabled
		{
			get
			{
				return GameObject.activeSelf;
			}
			set
			{
				GameObject.SetActive(value);
			}
		}

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

		public Vector3 LocalPosition
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return Transform.localPosition;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				Transform.localPosition = value;
			}
		}

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

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

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

		public float StartSize
		{
			get
			{
				//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)
				//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)
				MainModule val = psm;
				MinMaxCurve startSize = ((MainModule)(ref val)).startSize;
				return ((MinMaxCurve)(ref startSize)).constant;
			}
			set
			{
				//IL_0006: 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_000f: 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_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)
				//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)
				MainModule val = psm;
				MinMaxCurve startSpeed = ((MainModule)(ref val)).startSpeed;
				return ((MinMaxCurve)(ref startSpeed)).constant;
			}
			set
			{
				//IL_0006: 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_000f: 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_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)
				//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)
				MainModule val = psm;
				MinMaxCurve startLifetime = ((MainModule)(ref val)).startLifetime;
				return ((MinMaxCurve)(ref startLifetime)).constant;
			}
			set
			{
				//IL_0006: 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_000f: 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_0006: 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)
				SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime;
				return ((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled;
			}
			set
			{
				//IL_0006: 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)
				SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime;
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = value;
			}
		}

		public MinMaxCurve SizeOverLifetime
		{
			get
			{
				//IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references)
				SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime;
				return ((SizeOverLifetimeModule)(ref sizeOverLifetime)).size;
			}
			set
			{
				//IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references)
				SizeOverLifetimeModule sizeOverLifetime = ps.sizeOverLifetime;
				((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = value;
			}
		}

		public Overlay(Transform transform)
		{
			//IL_0038: 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)
			Transform = transform;
			GameObject = ((Component)transform).gameObject;
			ps = ((Component)transform).GetComponentInChildren<ParticleSystem>();
			psr = ((Component)transform).GetComponentInChildren<ParticleSystemRenderer>();
			psm = ps.main;
		}
	}
	public abstract class OverlayVisualizer : MonoBehaviour
	{
		protected Overlay primary;

		protected Overlay secondary;

		protected Overlay tertiary;

		protected HoverInfo hoverInfo;

		internal static readonly Vector3 VerticalOffset = new Vector3(0f, 0.075f, 0f);

		private void Update()
		{
			//IL_007b: 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);
				tertiary = new Overlay(transform);
				hoverInfo = new HoverInfo(val2);
				tertiary.StartColor = new Color(255f, 255f, 255f);
				primary.Enabled = false;
				secondary.Enabled = false;
				tertiary.Enabled = false;
				Initialize();
			}
			OnRefresh();
		}

		protected abstract void Initialize();

		protected abstract void OnRefresh();

		protected void SpeedUp(Overlay overlay)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0041: 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);
			overlay.StartLifetime = 2f;
			overlay.SizeOverLifetime = sizeOverLifetime;
		}

		protected void Freeze(Overlay overlay)
		{
			overlay.StartSpeed = 0f;
			overlay.SizeOverLifetimeEnabled = false;
		}

		protected void VisualizeTerraformingBounds(Overlay overlay)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			overlay.StartSize = 3f;
			((Renderer)overlay.psr).material.mainTexture = (Texture)(object)IconCache.Box;
			overlay.LocalPosition = VerticalOffset;
		}

		protected void VisualizeIconInsideTerraformingBounds(Overlay overlay, Texture iconTexture)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			overlay.StartSize = 2.5f;
			((Renderer)overlay.psr).material.mainTexture = iconTexture;
			overlay.LocalPosition = VerticalOffset;
		}

		protected void VisualizeRecoloringBounds(Overlay overlay)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			overlay.StartSize = 3f;
			((Renderer)overlay.psr).material.mainTexture = (Texture)(object)IconCache.Box;
			overlay.LocalPosition = VerticalOffset;
		}

		protected void VisualizeIconInsideRecoloringBounds(Overlay overlay, Texture iconTexture)
		{
			//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)
			overlay.StartSize = 2.5f;
			((Renderer)overlay.psr).material.mainTexture = iconTexture;
			overlay.Position = ((Component)this).transform.position + VerticalOffset;
		}
	}
	public abstract class HoverInfoEnabled : OverlayVisualizer
	{
		protected override void Initialize()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			hoverInfo.Color = secondary.StartColor;
		}

		protected override void OnRefresh()
		{
			//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_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_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)
			hoverInfo.Enabled = TerrainTools.Instance.IsHoverInforEnabled;
			if (hoverInfo.Enabled)
			{
				hoverInfo.RotateToPlayer();
				Vector3 val = secondary.Position - OverlayVisualizer.VerticalOffset;
				hoverInfo.Text = $"x: {val.x:0}, y: {val.y:0.000}, z: {val.z:0}";
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "SetInvalidPlacementHeightlight")]
	public static class OverlayVisualizationRedshiftHeigthlightBlocker
	{
		private static bool Prefix(Piece __instance)
		{
			return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInChildren<OverlayVisualizer>());
		}
	}
	public class LevelGroundOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			base.Initialize();
			SpeedUp(secondary);
			VisualizeTerraformingBounds(secondary);
		}

		protected override void OnRefresh()
		{
			base.OnRefresh();
			primary.Enabled = false;
			secondary.Enabled = true;
		}
	}
	public class RaiseGroundOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			base.Initialize();
			Freeze(secondary);
			Freeze(tertiary);
			VisualizeTerraformingBounds(secondary);
			VisualizeTerraformingBounds(tertiary);
		}

		protected override void OnRefresh()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			base.OnRefresh();
			primary.Enabled = true;
			secondary.Enabled = true;
			GroundLevelSpinner.Refresh();
			secondary.LocalPosition = new Vector3(0f, GroundLevelSpinner.Value, 0f);
			Vector3 val = secondary.Position - OverlayVisualizer.VerticalOffset;
			if (GroundLevelSpinner.Value > 0f)
			{
				float y = secondary.LocalPosition.y;
				hoverInfo.Text = $"x: {val.x:0}, y: {val.y - y:0.000}, z: {val.z:0}\n\nh: +{y:0.000}";
			}
			else
			{
				hoverInfo.Text = $"x: {val.x:0}, y: {val.y:0.000}, z: {val.z:0}";
			}
			tertiary.Enabled = true;
		}
	}
	public class SquarePathOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			base.Initialize();
			SpeedUp(secondary);
			VisualizeRecoloringBounds(secondary);
		}

		protected override void OnRefresh()
		{
			base.OnRefresh();
			primary.Enabled = false;
			secondary.Enabled = true;
		}
	}
	public class CultivateOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			base.Initialize();
			SpeedUp(secondary);
			VisualizeRecoloringBounds(secondary);
		}

		protected override void OnRefresh()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			base.OnRefresh();
			primary.Enabled = false;
			secondary.Enabled = true;
			hoverInfo.Color = secondary.Color;
		}
	}
	public class SeedGrassOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			Freeze(secondary);
			VisualizeRecoloringBounds(secondary);
			primary.StartSize = 3f;
			primary.LocalPosition = new Vector3(0f, 2.5f, 0f);
		}

		protected override void OnRefresh()
		{
			base.OnRefresh();
			primary.Enabled = true;
			secondary.Enabled = true;
		}
	}
	public class RemoveModificationsOverlayVisualizer : OverlayVisualizer
	{
		protected override void Initialize()
		{
			Freeze(primary);
			SpeedUp(secondary);
			VisualizeTerraformingBounds(primary);
			VisualizeIconInsideTerraformingBounds(secondary, (Texture)(object)IconCache.Cross);
		}

		protected override void OnRefresh()
		{
			primary.Enabled = true;
			secondary.Enabled = true;
		}
	}
	public abstract class UndoRedoModificationsOverlayVisualizer : OverlayVisualizer
	{
		protected override void Initialize()
		{
			Freeze(primary);
			Freeze(secondary);
			VisualizeRecoloringBounds(primary);
			VisualizeIconInsideRecoloringBounds(secondary, (Texture)(object)Icon());
		}

		protected override void OnRefresh()
		{
			primary.Enabled = true;
			secondary.Enabled = true;
		}

		protected abstract Texture2D Icon();
	}
	public class UndoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer
	{
		protected override Texture2D Icon()
		{
			return IconCache.Undo;
		}
	}
	public class RedoModificationsOverlayVisualizer : UndoRedoModificationsOverlayVisualizer
	{
		protected override Texture2D Icon()
		{
			return IconCache.Redo;
		}
	}
}
namespace TerrainTools.Tools
{
	internal static class ToolConfigs
	{
		internal static Dictionary<string, ToolDB> ToolConfigsMap;

		static ToolConfigs()
		{
			Dictionary<string, ToolDB> obj = new Dictionary<string, ToolDB>
			{
				{
					"mud_road_v2_sq",
					new ToolDB("mud_road_v2_sq", "mud_road_v2", "Level ground (square)", "Levels ground according to the world grid based on player position. Use shift+click to level ground based on where you are pointing instead (this will smooth the terrain).", IconCache.MudRoadSquare, PieceTables.Hoe, 1, typeof(LevelGroundOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1)
				},
				{
					"raise_v2_precise",
					new ToolDB("raise_v2_precise", "raise_v2", "Raise ground (precision)", "Raise ground with precision accuracy by using scroll wheel to set ground height.", IconCache.RaiseSquare, PieceTables.Hoe, 2, typeof(RaiseGroundOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1)
				}
			};
			Texture2D lower = IconCache.Lower;
			float? raiseRadius = 1.5f;
			float? raisePower = 0.5f;
			float? raiseDelta = -0.5f;
			Requirement[] requirements = Array.Empty<Requirement>();
			obj.Add("lower_v2", new ToolDB("lower_v2", "raise_v2", "Lower ground", "Lowers ground.", lower, "_ShovelPieceTable", -1, null, null, null, null, raiseRadius, raisePower, raiseDelta, null, null, null, null, null, requirements, invertGhost: true, (UsageTagFlags)1));
			obj.Add("path_v2_square", new ToolDB("path_v2_square", "path_v2", "Pathen (square)", "Creates a dirt path according to the world grid without affecting ground height.", IconCache.MudRoadPathSquare, PieceTables.Hoe, 3, typeof(SquarePathOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			obj.Add("paved_road_v2_square", new ToolDB("paved_road_v2_square", "paved_road_v2", "Paved road (square)", "Creates a paved path according to the world grid and levels ground based on player position. Use shift+click to level ground based on where you are pointing (this will smooth the terrain).", IconCache.PavedRoadSquare, PieceTables.Hoe, 4, typeof(SquarePathOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			Texture2D pavedRoadPath = IconCache.PavedRoadPath;
			string hoe = PieceTables.Hoe;
			bool? smooth = false;
			obj.Add("paved_road_v2_path", new ToolDB("paved_road_v2_path", "paved_road_v2", "Paved road (path)", "Creates a paved path without affecting ground height", pavedRoadPath, hoe, 4, null, null, null, null, null, null, null, smooth, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			Texture2D pavedRoadPathSquare = IconCache.PavedRoadPathSquare;
			string hoe2 = PieceTables.Hoe;
			Type? typeFromHandle = typeof(SquarePathOverlayVisualizer);
			smooth = false;
			obj.Add("paved_road_v2_path_square", new ToolDB("paved_road_v2_path_square", "paved_road_v2", "Paved road (path, square)", "Created a paved path according to the world grid without affecting ground height", pavedRoadPathSquare, hoe2, 4, typeFromHandle, null, null, null, null, null, null, smooth, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			Texture2D remove = IconCache.Remove;
			string hoe3 = PieceTables.Hoe;
			Type? typeFromHandle2 = typeof(RemoveModificationsOverlayVisualizer);
			smooth = false;
			bool? level = false;
			bool? raise = false;
			bool? clearPaint = false;
			obj.Add("remove_terrain_mods", new ToolDB("remove_terrain_mods", "mud_road_v2", "Remove Terrain Modifications", "Resets ground height and paint", remove, hoe3, 4, typeFromHandle2, level, null, raise, null, null, null, smooth, null, null, clearPaint, null, null, invertGhost: false, (UsageTagFlags)1));
			obj.Add("cultivate_v2_square", new ToolDB("cultivate_v2_square", "cultivate_v2", "Cultivate (square)", "Cultivates ground according to the world grid and levels terrain based on player position. Use shift+click to level ground based on where you are pointing (this will smooth the terrain).", IconCache.CultivateSquare, PieceTables.Cultivator, 1, typeof(CultivateOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			Texture2D cultivatePath = IconCache.CultivatePath;
			string cultivator = PieceTables.Cultivator;
			clearPaint = false;
			obj.Add("cultivate_v2_path", new ToolDB("cultivate_v2_path", "cultivate_v2", "Cultivate (path)", "Cultivates ground without affecting ground height.", cultivatePath, cultivator, 1, null, null, null, null, null, null, null, clearPaint, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			Texture2D cultivatePathSquare = IconCache.CultivatePathSquare;
			string cultivator2 = PieceTables.Cultivator;
			Type? typeFromHandle3 = typeof(CultivateOverlayVisualizer);
			clearPaint = false;
			obj.Add("cultivate_v2_path_square", new ToolDB("cultivate_v2_path_square", "cultivate_v2", "Cultivate (path, square)", "Cultivates ground according to the world grid without affecting ground height.", cultivatePathSquare, cultivator2, 1, typeFromHandle3, null, null, null, null, null, null, clearPaint, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			obj.Add("replant_v2_square", new ToolDB("replant_v2_square", "replant_v2", "Replant (square)", "Replants terrain according to world grid without affecting ground height.", IconCache.ReplantSquare, PieceTables.Cultivator, 2, typeof(SeedGrassOverlayVisualizer), null, null, null, null, null, null, null, null, null, null, null, null, invertGhost: false, (UsageTagFlags)1));
			ToolConfigsMap = obj;
		}
	}
	internal class ToolDB
	{
		public string name;

		public string basePrefab;

		public string pieceName;

		public string pieceDesc;

		public Texture2D icon;

		public string pieceTable;

		public int insertIndex;

		public Type overlayType;

		public bool? level;

		public float? levelRadius;

		public bool? raise;

		public float? raiseRadius;

		public float? raisePower;

		public float? raiseDelta;

		public bool? smooth;

		public float? smoothRadius;

		public float? smoothPower;

		public bool? clearPaint;

		public float? paintRadius;

		public Requirement[] requirements;

		public bool invertGhost;

		public UsageTagFlags usageTagFlags;

		public GameObject prefab;

		public ToolDB(string name, string basePrefab, string pieceName, string pieceDesc, Texture2D icon, string pieceTable, int insertIndex = -1, Type overlayType = null, bool? level = null, float? levelRadius = null, bool? raise = null, float? raiseRadius = null, float? raisePower = null, float? raiseDelta = null, bool? smooth = null, float? smoothRadius = null, float? smoothPower = null, bool? clearPaint = null, float? paintRadius = null, Requirement[] requirements = null, bool invertGhost = false, UsageTagFlags usageTagFlags = (UsageTagFlags)1)
		{
			//IL_00b6: 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)
			this.name = name;
			this.basePrefab = basePrefab;
			this.pieceName = pieceName;
			this.pieceDesc = pieceDesc;
			this.icon = icon;
			this.pieceTable = pieceTable;
			this.insertIndex = insertIndex;
			if (overlayType != null)
			{
				this.overlayType = overlayType;
			}
			this.level = level;
			this.levelRadius = levelRadius;
			this.raise = raise;
			this.raiseRadius = raiseRadius;
			this.raisePower = raisePower;
			this.raiseDelta = raiseDelta;
			this.smooth = smooth;
			this.smoothRadius = smoothRadius;
			this.smoothPower = smoothPower;
			this.clearPaint = clearPaint;
			this.paintRadius = paintRadius;
			this.requirements = requirements;
			this.invertGhost = invertGhost;
			this.usageTagFlags = usageTagFlags;
		}
	}
}
namespace TerrainTools.Properties
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resources
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					resourceMan = new ResourceManager("TerrainTools.Properties.Resources", typeof(Resources).Assembly);
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static Bitmap box => (Bitmap)ResourceManager.GetObject("box", resourceCulture);

		internal static Bitmap cross => (Bitmap)ResourceManager.GetObject("cross", resourceCulture);

		internal static Bitmap cultivate_v2_path => (Bitmap)ResourceManager.GetObject("cultivate_v2_path", resourceCulture);

		internal static Bitmap cultivate_v2_path_square => (Bitmap)ResourceManager.GetObject("cultivate_v2_path_square", resourceCulture);

		internal static Bitmap cultivate_v2_square => (Bitmap)ResourceManager.GetObject("cultivate_v2_square", resourceCulture);

		internal static Bitmap lower_v2 => (Bitmap)ResourceManager.GetObject("lower_v2", resourceCulture);

		internal static Bitmap mud_road_v2_square => (Bitmap)ResourceManager.GetObject("mud_road_v2_square", resourceCulture);

		internal static Bitmap path_v2_square => (Bitmap)ResourceManager.GetObject("path_v2_square", resourceCulture);

		internal static Bitmap paved_road_v2_path => (Bitmap)ResourceManager.GetObject("paved_road_v2_path", resourceCulture);

		internal static Bitmap paved_road_v2_path_square => (Bitmap)ResourceManager.GetObject("paved_road_v2_path_square", resourceCulture);

		internal static Bitmap paved_road_v2_square => (Bitmap)ResourceManager.GetObject("paved_road_v2_square", resourceCulture);

		internal static Bitmap raise => (Bitmap)ResourceManager.GetObject("raise", resourceCulture);

		internal static Bitmap raise_v2_square => (Bitmap)ResourceManager.GetObject("raise_v2_square", resourceCulture);

		internal static Bitmap redo => (Bitmap)ResourceManager.GetObject("redo", resourceCulture);

		internal static Bitmap remove => (Bitmap)ResourceManager.GetObject("remove", resourceCulture);

		internal static Bitmap replant_v2_square => (Bitmap)ResourceManager.GetObject("replant_v2_square", resourceCulture);

		internal static Bitmap ShovelIcon => (Bitmap)ResourceManager.GetObject("ShovelIcon", resourceCulture);

		internal static Bitmap smooth => (Bitmap)ResourceManager.GetObject("smooth", resourceCulture);

		internal static Bitmap undo => (Bitmap)ResourceManager.GetObject("undo", resourceCulture);

		internal Resources()
		{
		}
	}
}
namespace TerrainTools.Patches
{
	[HarmonyPatch(typeof(GameCamera))]
	internal static class GameCameraPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch("UpdateCamera")]
		private static IEnumerable<CodeInstruction> UpdateCameraTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: 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_0037: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Player), "CanRotatePiece", (Type[])null, (Type[])null), (string)null)
			}).SetInstructionAndAdvance(Transpilers.EmitDelegate<Func<Player, bool>>((Func<Player, bool>)UpdateCamera_BlockScroll_Delegate)).InstructionEnumeration();
		}

		private static bool UpdateCamera_BlockScroll_Delegate(Player localPlayer)
		{
			Piece val = ((localPlayer != null) ? localPlayer.GetSelectedPiece() : null);
			if ((Object)(object)((val != null) ? ((Component)val).gameObject : null) != (Object)null && (Object.op_Implicit((Object)(object)((Component)val).gameObject.GetComponentInChildren<RaiseGroundOverlayVisualizer>()) || RadiusModifier.ShouldModifyRadius() || SharpnessModifier.ShouldModifySharpness()))
			{
				return true;
			}
			return localPlayer.CanRotatePiece();
		}
	}
	[HarmonyPatch]
	internal static class HeightmapPatches
	{
		private static void CounterOffset(ref Vector3 worldPos)
		{
			worldPos.x += 0.5f;
			worldPos.z += 0.5f;
		}

		private static void UndoCounterOffset(ref Vector3 worldPos)
		{
			worldPos.x -= 0.5f;
			worldPos.z -= 0.5f;
		}

		public static float GetPaintMaskScale(this Heightmap hm)
		{
			float num = hm.m_width;
			return num / (num + 1f);
		}

		public static int GetPaintMaskWidth(this Heightmap hm)
		{
			return hm.m_width + 1;
		}

		public static Vector3 PaintMaskVertexToWorldPos(this Heightmap hm, int i, int j)
		{
			//IL_0006: 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_001e: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)hm).transform.position;
			int num = hm.GetPaintMaskWidth() / 2;
			float paintMaskScale = hm.GetPaintMaskScale();
			position.x += paintMaskScale * (float)(i - num);
			position.z += paintMaskScale * (float)(j - num);
			return position;
		}
	}
	[HarmonyPatch]
	internal class PlayerPatch
	{
		[HarmonyFinalizer]
		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		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_004c: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance) && ((Character)__instance).InPlaceMode() && !((Character)__instance).IsDead() && Object.op_Implicit((Object)(object)__instance.m_placementGhost) && Object.op_Implicit((Object)(object)__instance.m_placementGhost.GetComponent<OverlayVisualizer>()))
			{
				Vector3 position = __instance.m_placementGhost.transform.position;
				position.x = position.x.RoundToNearest(1f);
				position.z = position.z.RoundToNearest(1f);
				__instance.m_placementGhost.transform.position = position;
			}
		}
	}
}
namespace TerrainTools.Extensions
{
	public static class ConfigFileExtensions
	{
		public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}
	}
	internal static class EventExtensions
	{
		public static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
	internal static class FloatExtensions
	{
		private const float Tolerance = 1E-06f;

		internal static bool Equals(this float x, float y, float eps = 1E-06f)
		{
			float num = Mathf.Abs(x - y);
			if (!(num <= eps))
			{
				return num <= Mathf.Max(Mathf.Abs(x), Mathf.Abs(y)) * eps;
			}
			return true;
		}

		internal static float RoundToNearest(this float x, float precision)
		{
			if ((double)precision != 0.0)
			{
				return Mathf.Sign(x) * Mathf.Floor(Mathf.Abs(x) / precision + 0.5f) * precision;
			}
			return x;
		}
	}
	internal static class TerrainCompExtensions
	{
		internal struct SquareBounds
		{
			public int min;

			public int max;

			public SquareBounds(int min, int max)
			{
				this.min = min;
				this.max = max;
			}
		}

		public const int FixedRadius = 1;

		public const float RoundOff = 0.05f;

		public static int GetFixedRadius(this TerrainComp comp)
		{
			return 1;
		}

		public static int GetFixedRadius(this TerrainOp terrainOp)
		{
			return 1;
		}

		public static bool IsPrecisionModifier(this TerrainComp terrainComp)
		{
			return IsPrecisionModifier(terrainComp.m_lastOpRadius);
		}

		public static bool IsPrecisionModifier(this Settings settings)
		{
			if (settings.m_raise && IsPrecisionModifier(settings.m_raiseRadius))
			{
				return true;
			}
			if (settings.m_smooth && IsPrecisionModifier(settings.m_smoothRadius))
			{
				return true;
			}
			if (settings.m_paintCleared && IsPrecisionModifier(settings.m_paintRadius))
			{
				return true;
			}
			if (settings.m_level && IsPrecisionModifier(settings.m_levelRadius))
			{
				return true;
			}
			if (!settings.m_raise && !settings.m_smooth && !settings.m_paintCleared && !settings.m_level)
			{
				return true;
			}
			return false;
		}

		public static bool IsPrecisionModifier(float radius)
		{
			return radius == float.NegativeInfinity;
		}

		public static void RemoveTerrainModifications(this TerrainComp comp, Vector3 worldPos)
		{
			//IL_001c: 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)
			Log.LogInfo("[INIT] Remove Terrain Modifications", Log.InfoLevel.Medium);
			int fixedRadius = comp.GetFixedRadius();
			int num = comp.m_width + 1;
			comp.FindSquareBounds(worldPos, fixedRadius, out var xBounds, out var zBounds);
			Log.LogInfo($"worldPos: {worldPos}, Bounds (X,Z): Min=({xBounds.min}, {zBounds.min}), Max=({xBounds.max}, {zBounds.max})", Log.InfoLevel.Medium);
			for (int i = xBounds.min; i <= xBounds.max; i++)
			{
				for (int j = zBounds.min; j <= zBounds.max; j++)
				{
					int num2 = j * num + i;
					comp.m_levelDelta[num2] = 0f;
					comp.m_smoothDelta[num2] = 0f;
					comp.m_modifiedHeight[num2] = false;
					Log.LogInfo($"Vertex: ({i}, {j}), Index: {num2}", Log.InfoLevel.Medium);
				}
			}
			Log.LogInfo("[SUCCESS] Remove Terrain Modifications", Log.InfoLevel.Medium);
		}

		public static void PreciseRaiseTerrain(this TerrainComp comp, Vector3 worldPos, float delta)
		{
			//IL_001c: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo("[INIT] Raise Terrain Modification", Log.InfoLevel.Medium);
			int fixedRadius = comp.GetFixedRadius();
			int num = comp.m_width + 1;
			comp.FindSquareBounds(worldPos, fixedRadius, out var xBounds, out var zBounds);
			Log.LogInfo($"worldPos: {worldPos}, Bounds (X,Z): Min=({xBounds.min}, {zBounds.min}), Max=({xBounds.max}, {zBounds.max})", Log.InfoLevel.Medium);
			float num2 = worldPos.y - ((Component)comp).transform.position.y;
			Log.LogInfo($"worldPos: {worldPos}, delta: {delta}, refHeight: {num2}", Log.InfoLevel.Medium);
			for (int i = xBounds.min; i <= xBounds.max; i++)
			{
				for (int j = zBounds.min; j <= zBounds.max; j++)
				{
					float height = comp.m_hmap.GetHeight(i, j);
					float num3 = num2 + delta;
					if (delta < 0f && num3 > height)
					{
						continue;
					}
					if (delta >= 0f)
					{
						if (num3 < height)
						{
							continue;
						}
						if (num3 > height + delta)
						{
							num3 = height + delta;
						}
					}
					int num4 = j * num + i;
					float num5 = num3 - height + comp.m_smoothDelta[num4];
					comp.m_smoothDelta[num4] = 0f;
					comp.m_levelDelta[num4] += num5;
					comp.m_levelDelta[num4] = Mathf.Clamp(comp.m_levelDelta[num4], -8f, 8f);
					comp.m_modifiedHeight[num4] = true;
				}
			}
			Log.LogInfo("[SUCCESS] Raise Terrain Modification", Log.InfoLevel.Medium);
		}

		public static void PreciseSmoothTerrain(this TerrainComp comp, Vector3 worldPos)
		{
			//IL_001c: 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_0033: 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)
			Log.LogInfo("PreciseSmoothTerrain", Log.InfoLevel.Medium);
			int fixedRadius = comp.GetFixedRadius();
			int num = comp.m_width + 1;
			comp.FindSquareBounds(worldPos, fixedRadius, out var xBounds, out var zBounds);
			float num2 = worldPos.y - ((Component)comp).transform.position.y;
			Log.LogInfo($"worldPos: {worldPos}, Bounds (X,Z): Min=({xBounds.min}, {zBounds.min}), Max=({xBounds.max}, {zBounds.max})", Log.InfoLevel.Medium);
			for (int i = xBounds.min; i <= xBounds.max; i++)
			{
				for (int j = zBounds.min; j <= zBounds.max; j++)
				{
					int num3 = j * num + i;
					float height = comp.m_hmap.GetHeight(i, j);
					float num4 = num2 - height;
					float num5 = comp.m_smoothDelta[num3];
					comp.m_smoothDelta[num3] = Mathf.Clamp(num5 + num4, -1f, 1f);
					comp.m_modifiedHeight[num3] = true;
					Log.LogInfo($"Vertex: ({i}, {j}), Index: {num3}, tileH: {height}, deltaH: {num4}, prevSmoothDelta: {num5}, newSmoothDelta {comp.m_smoothDelta[num3]}", Log.InfoLevel.Medium);
				}
			}
			Log.LogInfo("[SUCCESS] Smooth Terrain Modification", Log.InfoLevel.Medium);
		}

		public static void PreciseRecolorTerrain(this TerrainComp comp, Vector3 worldPos, PaintType paintType)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Invalid comparison between Unknown and I4
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo("[INIT] PreciseRecolorTerrain", Log.InfoLevel.Medium);
			int num = default(int);
			int num2 = default(int);
			comp.m_hmap.WorldToVertexMask(worldPos, ref num, ref num2);
			float paintMaskScale = comp.m_hmap.GetPaintMaskScale();
			int num3 = Mathf.CeilToInt(1f / paintMaskScale);
			int num4 = Math.Max(num - num3, 0);
			int num5 = Math.Min(num + num3, comp.m_width);
			int num6 = Math.Max(num2 - num3, 0);
			int num7 = Math.Min(num2 + num3, comp.m_width);
			Color val = ResolveColor(paintType);
			bool flag = (int)paintType == 3;
			int num8 = comp.m_width + 1;
			for (int i = num4; i <= num5; i++)
			{
				for (int j = num6; j <= num7; j++)
				{
					comp.m_hmap.GetPaintMask(i, j);
					int num9 = j * num8 + i;
					Vector3 val2 = comp.m_hmap.PaintMaskVertexToWorldPos(i, j);
					float num10 = Mathf.Max(Mathf.Abs(val2.x - worldPos.x) + 0.5f * paintMaskScale - 1f, 0f);
					float num11 = Mathf.Max(Mathf.Abs(val2.z - worldPos.z) + 0.5f * paintMaskScale - 1f, 0f);
					if (!(num10 > paintMaskScale) && !(num11 > paintMaskScale))
					{
						comp.m_paintMask[num9] = val;
						comp.m_modifiedPaint[num9] = !flag;
						Log.LogInfo($"Vertex: ({i}, {j}), Index: {num9}, Color: {comp.m_paintMask[num9]}", Log.InfoLevel.Medium);
					}
				}
			}
			Log.LogInfo("[SUCCESS] Color Terrain Modification", Log.InfoLevel.Medium);
		}

		public static Color ResolveColor(PaintType paintType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected I4, but got Unknown
			//IL_0018: 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_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_0030: Unknown result type (might be due to invalid IL or missing references)
			return (Color)((int)paintType switch
			{
				0 => Heightmap.m_paintMaskDirt, 
				1 => Heightmap.m_paintMaskCultivated, 
				2 => Heightmap.m_paintMaskPaved, 
				3 => Heightmap.m_paintMaskNothing, 
				_ => Heightmap.m_paintMaskNothing, 
			});
		}

		private static void FindSquareBounds(this TerrainComp comp, Vector3 worldPos, int radius, out SquareBounds xBounds, out SquareBounds zBounds)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			int num = default(int);
			int num2 = default(int);
			comp.m_hmap.WorldToVertex(worldPos, ref num, ref num2);
			xBounds = new SquareBounds(Mathf.Max(0, num - radius), Mathf.Min(num + radius, comp.m_width));
			zBounds = new SquareBounds(Mathf.Max(0, num2 - radius), Mathf.Min(num2 + radius, comp.m_width));
		}

		private static Color BlendColor(Color currentColor, Color newColor, float t)
		{
			//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_0012: 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)
			//IL_002a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			return new Color(LerpToUpperOrLowerRange(currentColor.r, newColor.r, t), LerpToUpperOrLowerRange(currentColor.g, newColor.g, t), LerpToUpperOrLowerRange(currentColor.b, newColor.b, t), currentColor.a);
		}

		private static float LerpToUpperOrLowerRange(float currentVal, float newVal, float t)
		{
			float num = Mathf.Lerp(currentVal, newVal, t);
			if (currentVal > newVal)
			{
				num = Mathf.Clamp(num, Mathf.Min(1f - t, 0.5f), 1f);
			}
			else if (currentVal < newVal)
			{
				num = Mathf.Clamp(num, 0f, t);
			}
			return num;
		}
	}
}
namespace TerrainTools.Core
{
	public static class GroundLevelSpinner
	{
		public const string MouseScrollWheel = "Mouse ScrollWheel";

		public const float ScrollPrecision = 0.05f;

		public const float SuperiorScrollPrecisionMultiplier = 0.2f;

		public const float MaxSpinner = 1f;

		public const float MinSpinner = 0f;

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

		public static void Refresh()
		{
			float num = ScrollDelta();
			if (num > 0f)
			{
				Up(num);
			}
			if (num < 0f)
			{
				Down(num);
			}
		}

		private static float ScrollDelta()
		{
			float num = Input.GetAxis("Mouse ScrollWheel");
			if (num != 0f)
			{
				num = ((num > 0f) ? 0.05f : (-0.05f));
			}
			return num;
		}

		private static void Up(float scrollDelta)
		{
			if (Value + scrollDelta > 1f)
			{
				Value = 1f;
			}
			else
			{
				Value = Mathf.Round((Value + scrollDelta) * 100f) / 100f;
			}
		}

		private static void Down(float scrollDelta)
		{
			if (Value + scrollDelta < 0f)
			{
				Value = 0f;
			}
			else
			{
				Value = Mathf.Round((Value + scrollDelta) * 100f) / 100f;
			}
		}
	}
	internal static class InitManager
	{
		private static bool HasInitialized = false;

		internal static readonly Dictionary<string, GameObject> ToolRefs = new Dictionary<string, GameObject>();

		private static readonly Dictionary<string, List<int>> InsertionIndexes = new Dictionary<string, List<int>>();

		internal static void InitToolPieces()
		{
			if (HasInitialized)
			{
				return;
			}
			FixVanillaToolDescriptions();
			foreach (string key in ToolConfigs.ToolConfigsMap.Keys)
			{
				try
				{
					ToolDB toolDB = ToolConfigs.ToolConfigsMap[key];
					toolDB.prefab = MakeToolPiece(toolDB);
					Log.LogInfo("Created " + toolDB.name, Log.InfoLevel.Medium);
				}
				catch
				{
					Log.LogWarning("Failed to create: " + key);
				}
			}
			HasInitialized = true;
			UpdateTools();
		}

		internal static void FixVanillaToolDescriptions()
		{
			SetDescription("mud_road_v2", "Levels ground based on player position. Use shift + click to level ground based on where you are pointing (this will smooth the terrain).");
			SetDescription("raise_v2", "Raise grounds up to a maximum of 8 m above it's original height.");
			SetDescription("path_v2", "Creates a dirt path without affecting ground height.");
			SetDescription("paved_road_v2", "Creates a paved path and levels ground based on player position. Use shift+click to level ground based on where you are pointing (this will smooth the terrain).");
			SetDescription("cultivate_v2", "Cultivates ground and levels ground based on player position. Use shift + click to level ground based on where you are pointing (this will smooth the terrain).");
			SetDescription("replant_v2", "Replants terrain without affecting ground height.");
		}

		private static void SetDescription(string prefabName, string description)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
			Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				val.m_description = description;
			}
			else
			{
				Log.LogWarning("Could not set description for: " + prefabName);
			}
		}

		internal static void UpdatePlugin()
		{
			UpdateTools();
			UpdateShovelRecipe();
			((BaseUnityPlugin)TerrainTools.Instance).Config.Save();
			TerrainTools.Instance.UpdatePlugin = false;
		}

		private static void UpdateTools()
		{
			if (!HasInitialized)
			{
				return;
			}
			ForceUnequipTerrainTools();
			foreach (ToolDB value in ToolConfigs.ToolConfigsMap.Values)
			{
				RemovePieceInPieceTable(value);
			}
			foreach (string key in ToolConfigs.ToolConfigsMap.Keys)
			{
				if (TerrainTools.Instance.IsToolEnabled(key))
				{
					ToolDB toolDB = ToolConfigs.ToolConfigsMap[key];
					RegisterPieceInPieceTable(toolDB.prefab, toolDB.pieceTable, null, toolDB.insertIndex);
				}
			}
		}

		internal static void UpdatePieceTables()
		{
			foreach (string key in ToolConfigs.ToolConfigsMap.Keys)
			{
				try
				{
					ToolDB toolDB = ToolConfigs.ToolConfigsMap[key];
					toolDB.prefab = MakeToolPiece(toolDB);
					RegisterPieceInPieceTable(toolDB.prefab, toolDB.pieceTable, null, toolDB.insertIndex);
				}
				catch
				{
					Log.LogWarning("Failed to create: " + key);
				}
			}
		}

		private static void UpdateShovelRecipe()
		{
			if (Shovel.TryGetShovel(out var shovel))
			{
				shovel.Recipe.Recipe.m_enabled = TerrainTools.Instance.IsShovelEnabled;
			}
		}

		private static void ForceUnequipTerrainTools()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			ItemData rightItem = ((Humanoid)Player.m_localPlayer).GetRightItem();
			if (rightItem != null)
			{
				if (rightItem.m_shared.m_name == "$item_cultivator")
				{
					Log.LogWarning("AdvancedTerrainModifiers updated through config change, unequipping cultivator");
					((Humanoid)Player.m_localPlayer).HideHandItems(false, true);
				}
				if (rightItem.m_shared.m_name == "$item_hoe")
				{
					Log.LogWarning("AdvancedTerrainModifiers updated through config change, unequipping hoe");
					((Humanoid)Player.m_localPlayer).HideHandItems(false, true);
				}
			}
		}

		internal static GameObject MakeToolPiece(ToolDB toolDB)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			if (PieceManager.Instance.GetPiece(toolDB.pieceName) != null)
			{
				return null;
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(toolDB.name, toolDB.basePrefab);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Piece component = val.GetComponent<Piece>();
			component.m_icon = Sprite.Create(toolDB.icon, new Rect(0f, 0f, (float)((Texture)toolDB.icon).width, (float)((Texture)toolDB.icon).height), Vector2.zero);
			component.m_name = toolDB.pieceName;
			component.m_description = toolDB.pieceDesc;
			if (toolDB.requirements != null)
			{
				component.m_resources = toolDB.requirements;
			}
			Settings settings = val.GetComponent<TerrainOp>().m_settings;
			settings.m_level = UpdateValueIfNeeded(settings.m_level, toolDB.level);
			settings.m_levelRadius = UpdateValueIfNeeded(settings.m_levelRadius, toolDB.levelRadius);
			settings.m_raise = UpdateValueIfNeeded(settings.m_raise, toolDB.raise);
			settings.m_raiseRadius = UpdateValueIfNeeded(settings.m_raiseRadius, toolDB.raiseRadius);
			settings.m_raisePower = UpdateValueIfNeeded(settings.m_raisePower, toolDB.raisePower);
			settings.m_raiseDelta = UpdateValueIfNeeded(settings.m_raiseDelta, toolDB.raiseDelta);
			settings.m_smooth = UpdateValueIfNeeded(settings.m_smooth, toolDB.smooth);
			settings.m_smoothRadius = UpdateValueIfNeeded(settings.m_smoothRadius, toolDB.smoothRadius);
			settings.m_smoothPower = UpdateValueIfNeeded(settings.m_smoothPower, toolDB.smoothPower);
			settings.m_paintCleared = UpdateValueIfNeeded(settings.m_paintCleared, toolDB.clearPaint);
			settings.m_paintRadius = UpdateValueIfNeeded(settings.m_paintRadius, toolDB.paintRadius);
			if (toolDB.overlayType != null)
			{
				val.AddComponent(toolDB.overlayType);
			}
			if (toolDB.invertGhost)
			{
				Transform val2 = val.transform.Find("_GhostOnly");
				if ((Object)(object)val2 != (Object)null)
				{
					val2.localRotation = Quaternion.Euler(270f, 0f, 0f);
					val2.localPosition += new Vector3(0f, 2f, 0f);
				}
			}
			return val;
		}

		private static T UpdateValueIfNeeded<T>(T source, T? newValue) where T : struct
		{
			if (!newValue.HasValue)
			{
				return source;
			}
			return newValue.Value;
		}

		private static T UpdateValueIfNeeded<T>(T source, T newValue)
		{
			if (newValue == null)
			{
				return source;
			}
			return newValue;
		}

		private static void RegisterPieceInPieceTable(GameObject prefab, string pieceTable, string category, int position = -1)
		{
			//IL_00c6: 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)
			Piece component = prefab.GetComponent<Piece>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				throw new Exception("Prefab " + ((Object)prefab).name + " has no Piece component attached");
			}
			PieceTable pieceTable2 = PieceManager.Instance.GetPieceTable(pieceTable);
			if ((Object)(object)pieceTable2 == (Object)null)
			{
				throw new Exception("Could not find PieceTable " + pieceTable);
			}
			if (pieceTable2.m_pieces.Contains(prefab))
			{
				Log.LogDebug("Already added piece " + ((Object)prefab).name);
				return;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			if ((Object)(object)ZNetScene.instance != (Object)null && !ZNetScene.instance.m_namedPrefabs.ContainsKey(stableHashCode))
			{
				PrefabManager.Instance.RegisterToZNetScene(prefab);
			}
			if (!string.IsNullOrEmpty(category))
			{
				component.m_category = PieceManager.Instance.AddPieceCategory(category);
			}
			if (!InsertionIndexes.ContainsKey(pieceTable))
			{
				InsertionIndexes[pieceTable] = new List<int>();
			}
			int num = 0;
			if (position >= 0)
			{
				num = position + InsertionIndexes[pieceTable].Where((int x) => x <= position).Count();
			}
			else if (num >= pieceTable2.m_pieces.Count && pieceTable2.m_pieces.Count != 0)
			{
				Log.LogWarning("Piece insertion index is out of bounds");
			}
			if (position >= 0 && num < pieceTable2.m_pieces.Count)
			{
				pieceTable2.m_pieces.Insert(num, prefab);
				InsertionIndexes[pieceTable].Add(position);
			}
			else
			{
				pieceTable2.m_pieces.Add(prefab);
				InsertionIndexes[pieceTable].Add(pieceTable2.m_pieces.Count - 1);
			}
			Log.LogDebug("Added piece " + ((Object)prefab).name + " | Token: " + PieceExtension.TokenName(component));
		}

		internal static void RegisterTerrainOpInObjectDB(GameObject prefab)
		{
			TerrainOp val = default(TerrainOp);
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !prefab.TryGetComponent<TerrainOp>(ref val) || ObjectDB.instance.m_terrainOpsByHash == null || ObjectDB.instance.m_terrainOps == null)
			{
				return;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			if (ObjectDB.instance.m_terrainOpsByHash.TryGetValue(stableHashCode, out var value))
			{
				if ((Object)(object)value != (Object)(object)val)
				{
					Log.LogWarning($"TerrainOp prefab hash collision for {((Object)prefab).name} ({stableHashCode}); keeping the registered prefab");
				}
				return;
			}
			if (!ObjectDB.instance.m_terrainOps.Contains(val))
			{
				ObjectDB.instance.m_terrainOps.Add(val);
			}
			if (!ObjectDB.instance.m_terrainOpsByHash.ContainsKey(stableHashCode))
			{
				ObjectDB.instance.m_terrainOpsByHash.Add(stableHashCode, val);
			}
			Log.LogInfo("Registered TerrainOp " + ((Object)prefab).name + " in ObjectDB");
		}

		private static void RemovePieceInPieceTable(ToolDB toolDB)
		{
			GameObject prefab = toolDB.prefab;
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			PieceTable pieceTable = PieceManager.Instance.GetPieceTable(toolDB.pieceTable);
			if ((Object)(object)pieceTable == (Object)null)
			{
				throw new Exception("Could not find PieceTable " + toolDB.pieceTable);
			}
			int num = pieceTable.m_pieces.IndexOf(prefab);
			if (num < 0)
			{
				return;
			}
			pieceTable.m_pieces.Remove(prefab);
			Log.LogDebug("Removed piece " + ((Object)prefab).name);
			List<int> list = InsertionIndexes[toolDB.pieceTable];
			if (!list.Contains(num))
			{
				return;
			}
			list.Remove(num);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] > num)
				{
					list[i]--;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PreciseTerrainModifier))]
	public static class PreciseTerrainModifier
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(ClutterSystem), "ResetGrass")]
		private static void ResetGrassPrefix(ClutterSystem __instance, Vector3 center, ref float radius)
		{
			if (TerrainCompExtensions.IsPrecisionModifier(radius))
			{
				radius = 0.75f;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
		private static void ApplyOperationPrefix(TerrainComp __instance, TerrainOp modifier)
		{
			if (Object.op_Implicit((Object)(object)modifier) && Object.op_Implicit((Object)(object)((Component)modifier).gameObject) && Object.op_Implicit((Object)(object)((Component)modifier).gameObject.GetComponentInChildren<OverlayVisualizer>()))
			{
				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;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainOp), "GetRadius")]
		private static void GetRadiusPostfix(TerrainOp __instance, ref float __result)
		{
			if (Object.op_Implicit((Object)(object)__instance) && __instance.m_settings.IsPrecisionModifier())
			{
				__result = Mathf.Max(__result, (float)__instance.GetFixedRadius());
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "RPC_ApplyOperation")]
		private static void RPC_ApplyOperationPrefix(TerrainComp __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.m_nview) && !__instance.m_nview.IsOwner())
			{
				__instance.m_nview.ClaimOwnership();
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(700)]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPrefix(TerrainComp __instance, Vector3 pos, Settings modifier)
		{
			//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 (!modifier.m_level && !modifier.m_raise && !modifier.m_smooth && !modifier.m_paintCleared)
			{
				__instance.RemoveTerrainModifications(pos);
				__instance.PreciseRecolorTerrain(pos, (PaintType)3);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "SmoothTerrain")]
		private static bool SmoothTerrainPrefix(TerrainComp __instance, Vector3 worldPos, float radius)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (TerrainCompExtensions.IsPrecisionModifier(radius))
			{
				__instance.PreciseSmoothTerrain(worldPos);
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")]
		private static bool RaiseTerrainPrefix(TerrainComp __instance, Vector3 worldPos, float radius, float delta)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (TerrainCompExtensions.IsPrecisionModifier(radius))
			{
				__instance.PreciseRaiseTerrain(worldPos, delta);
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "PaintCleared")]
		private static bool PaintClearedPrefix(TerrainComp __instance, Vector3 worldPos, Vector3 rot, Settings settings)
		{
			//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)
			if (TerrainCompExtensions.IsPrecisionModifier(settings.m_paintRadius))
			{
				__instance.PreciseRecolorTerrain(worldPos, settings.m_paintType);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class RadiusModifier
	{
		private static bool RadiusToolIsInUse = false;

		private static float lastOriginalRadius;

		private static float lastModdedRadius;

		private static float lastTotalDelta;

		private static float lastRaiseRadius;

		private static float lastSmoothRadius;

		private static float lastPaintRadius;

		private static float lastLevelRadius;

		private static Vector3 lastGhostScale = Vector3.zero;

		private const float MinRadius = 0.5f;

		private const float Tolerance = 0.01f;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "Update")]
		private static void UpdatePrefix(Player __instance)
		{
			//IL_0050: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			TerrainOp terrainOp;
			if (!((Character)__instance).InPlaceMode() || Hud.IsPieceSelectionVisible())
			{
				if (RadiusToolIsInUse)
				{
					RadiusToolIsInUse = false;
					lastOriginalRadius = 0f;
					lastModdedRadius = 0f;
					lastTotalDelta = 0f;
					lastGhostScale = Vector3.zero;
				}
			}
			else if (IsValidSelectedPiece(__instance, out terrainOp))
			{
				if (ShouldModifyRadius())
				{
					SetRadius(terrainOp, Input.mouseScrollDelta.y * TerrainTools.Instance.RadiusScrollScale);
				}
				RefreshGhostScale(__instance);
			}
		}

		internal static bool IsValidSelectedPiece(Player player, out TerrainOp terrainOp)
		{
			Piece selectedPiece = player.GetSelectedPiece();
			if (!Object.op_Implicit((Object)(object)selectedPiece) || !Object.op_Implicit((Object)(object)((Component)selectedPiece).gameObject) || Object.op_Implicit((Object)(object)((Component)selectedPiece).gameObject.GetComponent<OverlayVisualizer>()))
			{
				terrainOp = null;
				return false;
			}
			terrainOp = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>();
			if (!Object.op_Implicit((Object)(object)terrainOp))
			{
				return false;
			}
			return true;
		}

		internal static bool ShouldModifyRadius()
		{
			//IL_0011: 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)
			if (TerrainTools.Instance.IsEnableRadiusModifier && Input.GetKey(TerrainTools.Instance.RadiusKey))
			{
				return Input.mouseScrollDelta.y != 0f;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPriority(100)]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPrefix(TerrainComp __instance, Settings modifier)
		{
			if (Object.op_Implicit((Object)(object)__instance) && modifier != null && !modifier.IsPrecisionModifier())
			{
				if (modifier.m_level)
				{
					lastLevelRadius = modifier.m_levelRadius;
					modifier.m_levelRadius = ModifyRadius(modifier.m_levelRadius, lastTotalDelta);
					Log.LogInfo($"Applying level radius {modifier.m_levelRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_raise)
				{
					lastRaiseRadius = modifier.m_raiseRadius;
					modifier.m_raiseRadius = ModifyRadius(modifier.m_raiseRadius, lastTotalDelta);
					Log.LogInfo($"Applying raise radius {modifier.m_raiseRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_smooth)
				{
					lastSmoothRadius = modifier.m_smoothRadius;
					modifier.m_smoothRadius = ModifyRadius(modifier.m_smoothRadius, lastTotalDelta);
					Log.LogInfo($"Applying smooth radius {modifier.m_smoothRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_paintCleared)
				{
					lastPaintRadius = modifier.m_paintRadius;
					modifier.m_paintRadius = ModifyRadius(modifier.m_paintRadius, lastTotalDelta);
					Log.LogInfo($"Applying paint radius {modifier.m_paintRadius}", Log.InfoLevel.Medium);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(700)]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPostfix(TerrainComp __instance, Settings modifier)
		{
			if (Object.op_Implicit((Object)(object)__instance) && modifier != null && !modifier.IsPrecisionModifier())
			{
				if (modifier.m_level)
				{
					modifier.m_levelRadius = lastLevelRadius;
					Log.LogInfo($"Resoted level radius {modifier.m_levelRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_raise)
				{
					modifier.m_raiseRadius = lastRaiseRadius;
					Log.LogInfo($"Restored raise radius {modifier.m_raiseRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_smooth)
				{
					modifier.m_smoothRadius = lastSmoothRadius;
					Log.LogInfo($"Restored smooth radius {modifier.m_smoothRadius}", Log.InfoLevel.Medium);
				}
				if (modifier.m_paintCleared)
				{
					modifier.m_paintRadius = lastPaintRadius;
					Log.LogInfo($"Restored paint radius {modifier.m_paintRadius}", Log.InfoLevel.Medium);
				}
			}
		}

		private static float ModifyRadius(float radius, float delta)
		{
			return Mathf.Clamp(radius + delta, 0.5f, TerrainTools.Instance.MaxRadius);
		}

		private static void SetRadius(TerrainOp terrainOp, float delta)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo($"Adjusting radius by {delta}", Log.InfoLevel.High);
			if (!RadiusToolIsInUse && Object.op_Implicit((Object)(object)terrainOp))
			{
				if (TryGetMaximumRadius(terrainOp, out var maxRadius))
				{
					RadiusToolIsInUse = true;
					lastOriginalRadius = maxRadius;
					lastModdedRadius = ModifyRadius(maxRadius, delta);
					lastTotalDelta += delta;
				}
			}
			else
			{
				lastModdedRadius = ModifyRadius(lastModdedRadius, delta);
				lastTotalDelta += delta;
			}
			Log.LogInfo($"Total delta {lastTotalDelta}", Log.InfoLevel.High);
			lastGhostScale = new Vector3(lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius);
		}

		private static void RefreshGhostScale(Player player)
		{
			//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_005b: 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_0076: 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)
			if (!RadiusToolIsInUse || !Object.op_Implicit((Object)(object)player.m_placementGhost))
			{
				return;
			}
			Transform val = player.m_placementGhost.transform.Find("_GhostOnly");
			if (Object.op_Implicit((Object)(object)val))
			{
				ParticleSystem componentInChildren = ((Component)val).GetComponentInChildren<ParticleSystem>();
				if (Object.op_Implicit((Object)(object)componentInChildren) && !(lastGhostScale == Vector3.zero) && Vector3.Distance(((Component)componentInChildren).transform.localScale, lastGhostScale) > 0.01f)
				{
					Log.LogInfo($"Adjusting ghost scale to {lastGhostScale}x", Log.InfoLevel.High);
					((Component)componentInChildren).transform.localScale = lastGhostScale;
				}
			}
		}

		private static bool TryGetMaximumRadius(TerrainOp terrainOp, out float maxRadius)
		{
			maxRadius = 0f;
			if (terrainOp.m_settings.m_level && maxRadius < terrainOp.m_settings.m_levelRadius)
			{
				maxRadius = terrainOp.m_settings.m_levelRadius;
			}
			if (terrainOp.m_settings.m_raise && maxRadius < terrainOp.m_settings.m_raiseRadius)
			{
				maxRadius = terrainOp.m_settings.m_raiseRadius;
			}
			if (terrainOp.m_settings.m_smooth && maxRadius < terrainOp.m_settings.m_smoothRadius)
			{
				maxRadius = terrainOp.m_settings.m_smoothRadius;
			}
			if (terrainOp.m_settings.m_paintCleared && maxRadius < terrainOp.m_settings.m_paintRadius)
			{
				maxRadius = terrainOp.m_settings.m_paintRadius;
			}
			return maxRadius != 0f;
		}
	}
	[HarmonyPatch]
	internal static class SharpnessModifier
	{
		private static bool SmoothToolIsInUse;

		private static float lastModdedSmoothPwr;

		private static float lastTotalSmoothDelta;

		private const float MinSmoothPwr = 1f;

		private const float MaxSmoothPwr = 30f;

		private static bool RaiseToolIsInUse;

		private static float lastModdedRaisePwr;

		private static float lastTotalRaiseDelta;

		private const float MinRaisePwr = 0.05f;

		private const float MaxRaisePwr = 1f;

		private static float lastRaisePower;

		private static float lastSmoothPower;

		private const float DisplayThreshold = 0.9f;

		private static float lastDisplayedSmoothSharpness;

		private static float lastDisplayedRaiseSharpness;

		[HarmonyPrefix]
		[HarmonyPriority(300)]
		[HarmonyPatch(typeof(Player), "Update")]
		private static void UpdatePrefix(Player __instance)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			if (!((Character)__instance).InPlaceMode() || Hud.IsPieceSelectionVisible())
			{
				if (SmoothToolIsInUse)
				{
					SmoothToolIsInUse = false;
					lastModdedSmoothPwr = 0f;
					lastTotalSmoothDelta = 0f;
					lastDisplayedSmoothSharpness = -1f;
					SetPower(__instance, 0f);
				}
				if (RaiseToolIsInUse)
				{
					RaiseToolIsInUse = false;
					lastModdedRaisePwr = 0f;
					lastTotalRaiseDelta = 0f;
					lastDisplayedRaiseSharpness = -1f;
					SetPower(__instance, 0f);
				}
			}
			else if (ShouldModifySharpness())
			{
				SetPower(__instance, Input.mouseScrollDelta.y * TerrainTools.Instance.SharpnessScrollScale);
			}
		}

		internal static bool ShouldModifySharpness()
		{
			//IL_0011: 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)
			if (TerrainTools.Instance.IsEnableSharpnessModifier && Input.GetKey(TerrainTools.Instance.SharpnessKey))
			{
				return Input.mouseScrollDelta.y != 0f;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPriority(101)]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPrefix(TerrainComp __instance, Settings modifier)
		{
			if (Object.op_Implicit((Object)(object)__instance) && modifier != null && !modifier.IsPrecisionModifier())
			{
				if (modifier.m_raise)
				{
					lastRaisePower = modifier.m_raisePower;
					modifier.m_raisePower = ModifyRaisePower(modifier.m_raisePower, lastTotalRaiseDelta);
					Log.LogInfo($"Applying raise power {modifier.m_raisePower}", Log.InfoLevel.Medium);
				}
				if (modifier.m_smooth)
				{
					lastSmoothPower = modifier.m_smoothPower;
					modifier.m_smoothPower = ModifySmoothPower(modifier.m_smoothPower, lastTotalSmoothDelta);
					Log.LogInfo($"Applying smooth power {modifier.m_smoothPower}", Log.InfoLevel.Medium);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(700)]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPostfix(TerrainComp __instance, Settings modifier)
		{
			if (Object.op_Implicit((Object)(object)__instance) && modifier != null && !modifier.IsPrecisionModifier())
			{
				if (modifier.m_raise)
				{
					modifier.m_raisePower = lastRaisePower;
					Log.LogInfo($"Restored raise power {modifier.m_raisePower}", Log.InfoLevel.Medium);
				}
				if (modifier.m_smooth)
				{
					modifier.m_smoothPower = lastSmoothPower;
					Log.LogInfo($"Restored smooth power {modifier.m_smoothPower}", Log.InfoLevel.Medium);
				}
			}
		}

		private static void SetPower(Player player, float delta)
		{
			Piece selectedPiece = player.GetSelectedPiece();
			if (!Object.op_Implicit((Object)(object)selectedPiece) || !Object.op_Implicit((Object)(object)((Component)selectedPiece).gameObject) || Object.op_Implicit((Object)(object)((Component)selectedPiece).gameObject.GetComponent<OverlayVisualizer>()))
			{
				return;
			}
			TerrainOp component = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			SetSmoothPower(component, delta);
			SetRaisePower(component, delta);
			List<string> list = new List<string>();
			if (SmoothToolIsInUse)
			{
				float smoothPowerDisplayValue = GetSmoothPowerDisplayValue(lastModdedSmoothPwr);
				if (Mathf.Abs(smoothPowerDisplayValue - lastDisplayedSmoothSharpness) > 0.9f)
				{
					lastDisplayedSmoothSharpness = Mathf.Round(smoothPowerDisplayValue);
					list.Add($"Terrain tool smoothing sharpness: {smoothPowerDisplayValue:0}%");
				}
			}
			if (RaiseToolIsInUse)
			{
				float raisePowerDisplayValue = GetRaisePowerDisplayValue(lastModdedRaisePwr);
				if (Mathf.Abs(raisePowerDisplayValue - lastDisplayedRaiseSharpness) > 0.9f)
				{
					lastDisplayedRaiseSharpness = Mathf.Round(raisePowerDisplayValue);
					string arg = ((component.m_settings.m_raiseDelta < 0f) ? "dig" : "raise");
					list.Add($"Terrain tool {arg} sharpness: {raisePowerDisplayValue:0}%");
				}
			}
			if (SmoothToolIsInUse || RaiseToolIsInUse)
			{
				Sprite icon = player.m_placementGhost.GetComponent<Piece>().m_icon;
				if ((Object)(object)icon != (Object)null && list.Count > 0)
				{
					((Character)player).Message((MessageType)2, string.Join("\n", list.ToArray()), 0, icon, false);
				}
			}
		}

		private static void SetSmoothPower(TerrainOp terrainOp, float delta)
		{
			if (terrainOp.m_settings.m_smooth)
			{
				Log.LogInfo($"Adjusting Smooth Power by {delta}", Log.InfoLevel.High);
				if (!SmoothToolIsInUse)
				{
					SmoothToolIsInUse = true;
					lastModdedSmoothPwr = ModifySmoothPower(terrainOp.m_settings.m_smoothPower, delta);
				}
				else
				{
					lastModdedSmoothPwr = ModifySmoothPower(lastModdedSmoothPwr, delta);
				}
				lastTotalSmoothDelta += delta;
				Log.LogInfo($"Total smooth power delta {lastTotalSmoothDelta}", Log.InfoLevel.High);
			}
		}

		private static void SetRaisePower(TerrainOp terrainOp, float delta)
		{
			if (terrainOp.m_settings.m_raise)
			{
				delta = ConvertSmoothDeltaToRaiseDelta(delta);
				Log.LogInfo($"Adjusting Raise Power by {delta}", Log.InfoLevel.High);
				if (!RaiseToolIsInUse)
				{
					RaiseToolIsInUse = true;
					lastModdedRaisePwr = ModifyRaisePower(terrainOp.m_settings.m_raisePower, delta);
				}
				else
				{
					lastModdedRaisePwr = ModifyRaisePower(lastModdedRaisePwr, delta);
				}
				lastTotalRaiseDelta += delta;
				Log.LogInfo($"Total raise power delta {lastTotalRaiseDelta}", Log.InfoLevel.High);
			}
		}

		private static float ConvertSmoothDeltaToRaiseDelta(float delta)
		{
			float num = delta / 29f;
			return -1f * num * 0.95f;
		}

		private static float GetSmoothPowerDisplayValue(float power)
		{
			return (power - 1f) / 29f * 100f;
		}

		private static float GetRaisePowerDisplayValue(float power, bool dig = false)
		{
			return (1f - power) / 0.95f * 100f;
		}

		private static float ModifySmoothPower(float power, float delta)
		{
			return Mathf.Clamp(power + delta, 1f, 30f);
		}

		private static float ModifyRaisePower(float power, float delta)
		{
			return Mathf.Clamp(power + delta, 0.05f, 1f);
		}
	}
	internal static class Shovel
	{
		private static bool HasBeenCreated;

		internal const string ShovelPrefabName = "ATM_Shovel";

		internal const string ShovelPieceTable = "_ShovelPieceTable";

		internal static CustomItem shovel;

		internal static bool TryGetShovel(out CustomItem shovel)
		{
			shovel = ItemManager.Instance.GetItem("ATM_Shovel");
			return shovel != null;
		}

		internal static void CreateShovel()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_003e: 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_006f: Unknow