Decompiled source of Pit Construtor v1.1.1

PitConstrutor.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using PitConstrutor.Terrain;
using ServerSync;
using SkillManager;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Pit Construtor")]
[assembly: AssemblyDescription("Mod Pit Construtor para Valheim - Sistema completo de habilidade de Construção, durabilidade, altura de suporte e eficiência de martelo.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Pit")]
[assembly: AssemblyProduct("Pit Construtor")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9BF5432D-9518-4D36-A6C2-A8C62D36B921")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PitConstrutor
{
	[BepInPlugin("org.bepinex.plugins.pit_construtor", "Pit Construtor", "1.1.1")]
	[BepInIncompatibility("org.bepinex.plugins.valheim_plus")]
	[BepInIncompatibility("org.bepinex.plugins.building")]
	public class PitConstrutorPlugin : BaseUnityPlugin
	{
		private enum Toggle
		{
			On = 1,
			Off = 0
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public bool? ShowRangeAsPercent;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class ChangeStaminaUsage
		{
			private static float stamina;

			private static bool modified;

			private static void Prefix(Player __instance, out ItemData? __state)
			{
				__state = ((Humanoid)__instance).GetRightItem();
				modified = false;
				if (__state?.m_shared != null && (__state.m_shared.m_name == "$item_hammer" || __state.m_shared.m_name == "$item_hoe" || __state.m_shared.m_name == "$item_cultivator") && __state.m_shared.m_attack != null)
				{
					stamina = __state.m_shared.m_attack.m_attackStamina;
					Attack attack = __state.m_shared.m_attack;
					attack.m_attackStamina *= Mathf.Max(0f, 1f - ((Character)(object)__instance).GetSkillFactor("Building") * (float)staminaReductionPerLevel.Value);
					modified = true;
				}
			}

			private static void Finalizer(ItemData? __state)
			{
				if (modified && __state?.m_shared?.m_attack != null)
				{
					__state.m_shared.m_attack.m_attackStamina = stamina;
					modified = false;
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "OnPlaced")]
		public class AddZDO
		{
			public static bool forFree;

			[UsedImplicitly]
			private static void Postfix(WearNTear __instance)
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				ZNetView val = (((Object)(object)__instance.m_nview != (Object)null) ? __instance.m_nview : ((Component)__instance).GetComponent<ZNetView>());
				if ((Object)(object)val != (Object)null)
				{
					ZDO zDO = val.GetZDO();
					if (zDO != null)
					{
						float skillFactor = ((Character)(object)Player.m_localPlayer).GetSkillFactor("Building");
						zDO.Set("BuildingSkill Level", skillFactor);
						__instance.m_health *= 1f + skillFactor * (healthFactor.Value - 1f);
						forFree = false;
						if (freeBuildLevelRequirement.Value > 0)
						{
							forFree = Random.Range((float)freeBuildLevelRequirement.Value / 100f, 5.5f) <= skillFactor;
						}
						zDO.Set("BuildingSkill FreeBuild", forFree);
					}
				}
				((Character)(object)Player.m_localPlayer).RaiseSkill("Building");
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Awake")]
		private class IncreaseHealth
		{
			[UsedImplicitly]
			private static void Prefix(WearNTear __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				ZNetView val = (((Object)(object)__instance.m_nview != (Object)null) ? __instance.m_nview : ((Component)__instance).GetComponent<ZNetView>());
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				ZDO zDO = val.GetZDO();
				if (zDO != null)
				{
					float num = zDO.GetFloat("BuildingSkill Level", 0f);
					if (num > 0f)
					{
						__instance.m_health *= 1f + num * (healthFactor.Value - 1f);
					}
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")]
		private class BuildHigher
		{
			[UsedImplicitly]
			private static void Postfix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					ZNetView obj = (((Object)(object)__instance.m_nview != (Object)null) ? __instance.m_nview : ((Component)__instance).GetComponent<ZNetView>());
					float? obj2;
					if (obj == null)
					{
						obj2 = null;
					}
					else
					{
						ZDO zDO = obj.GetZDO();
						obj2 = ((zDO != null) ? new float?(zDO.GetFloat("BuildingSkill Level", 0f)) : ((float?)null));
					}
					float num = obj2 ?? ((Character)(object)Player.m_localPlayer)?.GetSkillFactor("Building") ?? 0f;
					if (num > 0f)
					{
						maxSupport *= 1f + num * (maximumSupportFactor.Value - 1f);
						horizontalLoss *= 1f - num * (1f - supportLossFactor.Value);
						verticalLoss *= 1f - num * (1f - supportLossFactor.Value);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private class ResetFlag
		{
			private static void Finalizer()
			{
				AddZDO.forFree = false;
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private class BuildingIsFree
		{
			private class SkipConsumeResourcesException : Exception
			{
			}

			[HarmonyPriority(800)]
			private static void Prefix()
			{
				if (AddZDO.forFree)
				{
					throw new SkipConsumeResourcesException();
				}
			}

			private static Exception? Finalizer(Exception __exception)
			{
				if (!(__exception is SkipConsumeResourcesException))
				{
					return __exception;
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		private class RecoverResources
		{
			private static bool Prefix(Piece __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return true;
				}
				ZNetView val = (((Object)(object)__instance.m_nview != (Object)null) ? __instance.m_nview : ((Component)__instance).GetComponent<ZNetView>());
				if ((Object)(object)val != (Object)null)
				{
					ZDO zDO = val.GetZDO();
					if (zDO != null)
					{
						return !zDO.GetBool("BuildingSkill FreeBuild", false);
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class ReduceHammerDurabilityLoss
		{
			private static bool reduced;

			private static void Prefix(Player __instance)
			{
				reduced = false;
				if (durabilityUsageLevelRequirement.Value > 0 && (Object)(object)__instance != (Object)null && (float)durabilityUsageLevelRequirement.Value <= ((Character)(object)__instance).GetSkillFactor("Building") * 100f)
				{
					ItemData rightItem = ((Humanoid)__instance).GetRightItem();
					if (rightItem != null && rightItem.m_shared != null && (rightItem.m_shared.m_name == "$item_hammer" || rightItem.m_shared.m_name == "$item_hoe" || rightItem.m_shared.m_name == "$item_cultivator"))
					{
						SharedData shared = rightItem.m_shared;
						shared.m_useDurabilityDrain *= 0.7f;
						reduced = true;
					}
				}
			}

			private static void Finalizer(Player __instance)
			{
				if (reduced && (Object)(object)__instance != (Object)null)
				{
					ItemData rightItem = ((Humanoid)__instance).GetRightItem();
					if (rightItem != null && rightItem.m_shared != null)
					{
						SharedData shared = rightItem.m_shared;
						shared.m_useDurabilityDrain /= 0.7f;
						reduced = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class TerrainSynergySkillGain
		{
			[HarmonyPostfix]
			private static void Postfix(Player __instance, Piece piece)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (TerrainConfig.EnableTerrainSynergy == null || TerrainConfig.EnableTerrainSynergy.Value) && (Object)(object)piece != (Object)null && ((Object)(object)((Component)piece).GetComponent<TerrainOp>() != (Object)null || (Object)(object)((Component)piece).GetComponent<TerrainModifier>() != (Object)null || ((Object)(object)((Component)piece).gameObject != (Object)null && ((Object)(object)((Component)piece).gameObject.GetComponent<TerrainOp>() != (Object)null || (Object)(object)((Component)piece).gameObject.GetComponent<TerrainModifier>() != (Object)null))))
				{
					((Character)(object)__instance).RaiseSkill("Building");
				}
			}
		}

		[HarmonyPatch(typeof(Skills), "IsSkillValid")]
		private static class EnsureBuildingSkillValid
		{
			[HarmonyPostfix]
			private static void Postfix(SkillType type, ref bool __result)
			{
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Invalid comparison between Unknown and I4
				if (!__result && (int)type == Math.Abs(StringExtensionMethods.GetStableHashCode("Building")))
				{
					__result = true;
				}
			}
		}

		private const string ModName = "Pit Construtor";

		private const string ModVersion = "1.1.1";

		private const string ModGUID = "org.bepinex.plugins.pit_construtor";

		private static readonly ConfigSync configSync = new ConfigSync("org.bepinex.plugins.pit_construtor")
		{
			DisplayName = "Pit Construtor",
			CurrentVersion = "1.1.1",
			MinimumRequiredVersion = "1.1.1"
		};

		private static ConfigEntry<Toggle> serverConfigLocked = null;

		private static ConfigEntry<float> maximumSupportFactor = null;

		private static ConfigEntry<float> supportLossFactor = null;

		private static ConfigEntry<float> healthFactor = null;

		private static ConfigEntry<int> freeBuildLevelRequirement = null;

		private static ConfigEntry<int> durabilityUsageLevelRequirement = null;

		private static ConfigEntry<float> experienceGainedFactor = null;

		private static ConfigEntry<int> experienceLoss = null;

		private static ConfigEntry<int> staminaReductionPerLevel = null;

		private static Skill building = null;

		private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

		private ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		public void Awake()
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Expected O, but got Unknown
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Expected O, but got Unknown
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			building = new Skill("Building", "building-icon.png");
			building.Description.English("Increases the health of pieces built by you and you can build higher.");
			building.Name.German("Bauen");
			building.Description.German("Erhöht die Lebenspunkte von Bauten, die von dir errichtet wurden und du kannst höher bauen.");
			building.Name.Portuguese_Brazilian("Construção");
			building.Description.Portuguese_Brazilian("Aumenta a vida das peças construídas por você e permite construir estruturas mais altas.");
			building.Name.Portuguese_European("Construção");
			building.Description.Portuguese_European("Aumenta a vida das peças construídas por você e permite construir estruturas mais altas.");
			building.Configurable = false;
			serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			configSync.AddLockingConfigEntry<Toggle>(serverConfigLocked);
			maximumSupportFactor = config("2 - Building", "Maximum Support Factor", 1.5f, new ConfigDescription("Maximum support factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			supportLossFactor = config("2 - Building", "Support Loss Factor", 0.75f, new ConfigDescription("Support loss factor for vertical and horizontal building at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			healthFactor = config("2 - Building", "Health Factor", 3f, new ConfigDescription("Health factor for building pieces at skill level 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			freeBuildLevelRequirement = config("2 - Building", "Free Build Level Requirement", 50, new ConfigDescription("Minimum required skill level to be able to receive free building pieces. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false
				}
			}));
			durabilityUsageLevelRequirement = config("2 - Building", "Durability Increase Level Requirement", 30, new ConfigDescription("Minimum required skill level to reduce the durability usage of hammers by 30%. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ShowRangeAsPercent = false
				}
			}));
			staminaReductionPerLevel = config("2 - Building", "Stamina Reduction per Level", 1, new ConfigDescription("Reduces the stamina usage while building. Percentage stamina reduction per level. 0 is disabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			experienceGainedFactor = config("3 - Other", "Skill Experience Gain Factor", 1f, new ConfigDescription("Factor for experience gained for the building skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), Array.Empty<object>()));
			experienceGainedFactor.SettingChanged += delegate
			{
				building.SkillGainFactor = experienceGainedFactor.Value;
			};
			building.SkillGainFactor = experienceGainedFactor.Value;
			experienceLoss = config("3 - Other", "Skill Experience Loss", 0, new ConfigDescription("How much experience to lose in the building skill on death.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			experienceLoss.SettingChanged += delegate
			{
				building.SkillLoss = experienceLoss.Value;
			};
			building.SkillLoss = experienceLoss.Value;
			TerrainLog.Init(((BaseUnityPlugin)this).Logger);
			TerrainConfig.Init(((BaseUnityPlugin)this).Config, configSync);
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			new Harmony("org.bepinex.plugins.pit_construtor").PatchAll(executingAssembly);
		}
	}
}
namespace PitConstrutor.Terrain
{
	[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)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			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>()) || (TerrainConfig.EnableRadiusModifier.Value && Input.GetKey(TerrainConfig.RadiusKey.Value)) || (TerrainConfig.EnableHardnessModifier.Value && Input.GetKey(TerrainConfig.HardnessKey.Value))))
			{
				return true;
			}
			if ((Object)(object)localPlayer != (Object)null)
			{
				return localPlayer.CanRotatePiece();
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class PlayerPlacementGhostPatch
	{
		[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_004a: 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_006d: 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)
			//IL_00c4: 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;
				Heightmap val = Heightmap.FindHeightmap(position);
				if (Object.op_Implicit((Object)(object)val))
				{
					int num = default(int);
					int num2 = default(int);
					val.WorldToVertex(position, ref num, ref num2);
					position.x = ((Component)val).transform.position.x + (float)(num - val.m_width / 2) * val.m_scale;
					position.z = ((Component)val).transform.position.z + (float)(num2 - val.m_width / 2) * val.m_scale;
					__instance.m_placementGhost.transform.position = position;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "Update")]
		private static void PlayerUpdatePostfix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RadiusModifier.Tick(__instance);
				HardnessModifier.Tick(__instance);
			}
		}
	}
	public static class GroundLevelSpinner
	{
		public const string MouseScrollWheel = "Mouse ScrollWheel";

		public const float ScrollPrecision = 0.05f;

		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);
			}
			else if (num < 0f)
			{
				Down(num);
			}
		}

		private static float ScrollDelta()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (TerrainConfig.EnableHardnessModifier != null && TerrainConfig.EnableHardnessModifier.Value && Input.GetKey(TerrainConfig.HardnessKey.Value))
			{
				return 0f;
			}
			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;
			}
		}
	}
	[HarmonyPatch]
	internal static class HardnessModifier
	{
		private static bool SmoothToolIsInUse = false;

		private static float lastModdedSmoothPwr;

		private static float lastTotalSmoothDelta;

		private const float MinSmoothPwr = 1f;

		private const float MaxSmoothPwr = 30f;

		private static bool RaiseToolIsInUse = false;

		private static TerrainOp? activeRaiseTool;

		private static float lastModdedRaisePwr;

		private static float lastTotalRaiseDelta;

		private const float MinRaisePwr = 0.05f;

		private const float MaxRaisePwr = 1f;

		private const float DisplayThreshold = 0.9f;

		private static float lastDisplayedSmoothHardness = -1f;

		private static float lastDisplayedRaiseHardness = -1f;

		internal static void Tick(Player __instance)
		{
			//IL_00a8: 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;
					lastDisplayedSmoothHardness = -1f;
				}
				SelectRaiseTool(null);
			}
			else
			{
				Piece selectedPiece = __instance.GetSelectedPiece();
				TerrainOp val = ((Object.op_Implicit((Object)(object)selectedPiece) && Object.op_Implicit((Object)(object)((Component)selectedPiece).gameObject)) ? ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>() : null);
				SelectRaiseTool((Object.op_Implicit((Object)(object)val) && val.m_settings.m_raise) ? val : null);
				if (ShouldModifyHardness())
				{
					SetPower(__instance, Input.mouseScrollDelta.y * TerrainConfig.HardnessScrollScale.Value);
				}
			}
		}

		internal static bool ShouldModifyHardness()
		{
			//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 (TerrainConfig.EnableHardnessModifier.Value && Input.GetKey(TerrainConfig.HardnessKey.Value))
			{
				return Input.mouseScrollDelta.y != 0f;
			}
			return false;
		}

		internal static float CurrentRaisePower(float defaultPower)
		{
			if (!RaiseToolIsInUse)
			{
				return ModifyRaisePower(defaultPower, 0f);
			}
			return lastModdedRaisePwr;
		}

		private static void SelectRaiseTool(TerrainOp? terrainOp)
		{
			if (!((Object)(object)activeRaiseTool == (Object)(object)terrainOp))
			{
				activeRaiseTool = terrainOp;
				RaiseToolIsInUse = false;
				lastModdedRaisePwr = 0f;
				lastTotalRaiseDelta = 0f;
				lastDisplayedRaiseHardness = -1f;
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(600)]
		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		private static void AwakePrefix(TerrainOp __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)((Component)__instance).gameObject))
			{
				return;
			}
			OverlayVisualizer component = ((Component)__instance).gameObject.GetComponent<OverlayVisualizer>();
			if (!Object.op_Implicit((Object)(object)component) || component is RaiseGroundOverlayVisualizer)
			{
				if (__instance.m_settings.m_raise)
				{
					__instance.m_settings.m_raisePower = ModifyRaisePower(__instance.m_settings.m_raisePower, lastTotalRaiseDelta);
				}
				if (__instance.m_settings.m_smooth)
				{
					__instance.m_settings.m_smoothPower = ModifySmoothPower(__instance.m_settings.m_smoothPower, lastTotalSmoothDelta);
				}
			}
		}

		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))
			{
				return;
			}
			OverlayVisualizer component = ((Component)selectedPiece).gameObject.GetComponent<OverlayVisualizer>();
			if (Object.op_Implicit((Object)(object)component) && !(component is RaiseGroundOverlayVisualizer))
			{
				return;
			}
			TerrainOp component2 = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>();
			if (!Object.op_Implicit((Object)(object)component2))
			{
				return;
			}
			SetSmoothPower(component2, delta);
			SetRaisePower(component2, delta);
			List<string> list = new List<string>();
			if (SmoothToolIsInUse)
			{
				float smoothPowerDisplayValue = GetSmoothPowerDisplayValue(lastModdedSmoothPwr);
				if (Mathf.Abs(smoothPowerDisplayValue - lastDisplayedSmoothHardness) > 0.9f)
				{
					lastDisplayedSmoothHardness = Mathf.Round(smoothPowerDisplayValue);
					list.Add(string.Format("{0} {1:0}%", Localization.instance.Localize("$atmc_smoothing_hardness"), smoothPowerDisplayValue));
				}
			}
			if (RaiseToolIsInUse)
			{
				float raisePowerDisplayValue = GetRaisePowerDisplayValue(lastModdedRaisePwr);
				if (Mathf.Abs(raisePowerDisplayValue - lastDisplayedRaiseHardness) > 0.9f)
				{
					lastDisplayedRaiseHardness = Mathf.Round(raisePowerDisplayValue);
					list.Add(string.Format("{0} {1:0}%", Localization.instance.Localize("$atmc_raise_hardness"), raisePowerDisplayValue));
				}
			}
			if (SmoothToolIsInUse || RaiseToolIsInUse)
			{
				Piece val = (Object.op_Implicit((Object)(object)player.m_placementGhost) ? player.m_placementGhost.GetComponent<Piece>() : null);
				Sprite val2 = (Object.op_Implicit((Object)(object)val) ? val.m_icon : null);
				if ((Object)(object)val2 != (Object)null && list.Count > 0)
				{
					((Character)player).Message((MessageType)2, string.Join("\n", list.ToArray()), 0, val2, false);
				}
			}
		}

		private static void SetSmoothPower(TerrainOp terrainOp, float delta)
		{
			if (terrainOp.m_settings.m_smooth)
			{
				float num = (SmoothToolIsInUse ? lastModdedSmoothPwr : terrainOp.m_settings.m_smoothPower);
				SmoothToolIsInUse = true;
				lastModdedSmoothPwr = ModifySmoothPower(num, delta);
				lastTotalSmoothDelta += lastModdedSmoothPwr - num;
			}
		}

		private static void SetRaisePower(TerrainOp terrainOp, float delta)
		{
			if (terrainOp.m_settings.m_raise)
			{
				SelectRaiseTool(terrainOp);
				delta = ConvertSmoothDeltaToRaiseDelta(delta);
				float num = (RaiseToolIsInUse ? lastModdedRaisePwr : terrainOp.m_settings.m_raisePower);
				RaiseToolIsInUse = true;
				lastModdedRaisePwr = ModifyRaisePower(num, delta);
				lastTotalRaiseDelta += lastModdedRaisePwr - num;
			}
		}

		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)
		{
			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);
		}
	}
	[HarmonyPatch(typeof(Heightmap), "RebuildRenderMesh")]
	internal static class HeightmapPaintGridPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Heightmap __instance)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.m_isDistantLod || !Object.op_Implicit((Object)(object)__instance.m_renderMesh))
			{
				return;
			}
			int num = __instance.m_width + 1;
			List<Vector2> s_tempUVs = Heightmap.s_tempUVs;
			if (num > 1 && __instance.m_renderMesh.vertexCount == num * num && s_tempUVs.Count == num * num)
			{
				for (int i = 0; i < s_tempUVs.Count; i++)
				{
					s_tempUVs[i] = new Vector2(PaintGridMath.TexelCenterUv(i % num, __instance.m_width), PaintGridMath.TexelCenterUv(i / num, __instance.m_width));
				}
				__instance.m_renderMesh.SetUVs(0, s_tempUVs);
			}
		}
	}
	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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			_gameObject = new GameObject("HoverInfo");
			_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 / Mathf.Max(0.001f, parentTransform.localScale.x), 0.1f / Mathf.Max(0.001f, parentTransform.localScale.y), 0.1f / Mathf.Max(0.001f, parentTransform.localScale.z));
			_textMesh.anchor = (TextAnchor)4;
			_textMesh.alignment = (TextAlignment)1;
			_textMesh.fontSize = 16;
		}

		public void RotateToPlayer()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)GameCamera.m_instance == (Object)null))
			{
				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? _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 MethodInfo? s_loadImageMethod;

		internal static Texture2D Remove => _remove ?? (_remove = LoadTexture("remove.png"));

		internal static Texture2D Box => _box ?? (_box = LoadTexture("box.png"));

		internal static Texture2D PavedRoadSquare => _pavedRoadSquare ?? (_pavedRoadSquare = LoadTexture("paved_road_v2_square.png"));

		internal static Texture2D PavedRoadPath => _pavedRoadPath ?? (_pavedRoadPath = LoadTexture("paved_road_v2_path.png"));

		internal static Texture2D PavedRoadPathSquare => _pavedRoadPathSquare ?? (_pavedRoadPathSquare = LoadTexture("paved_road_v2_path_square.png"));

		internal static Texture2D MudRoadSquare => _mudRoadSquare ?? (_mudRoadSquare = LoadTexture("mud_road_v2_square.png"));

		internal static Texture2D MudRoadPathSquare => _mudRoadPathSquare ?? (_mudRoadPathSquare = LoadTexture("path_v2_square.png"));

		internal static Texture2D ReplantSquare => _replantSquare ?? (_replantSquare = LoadTexture("replant_v2_square.png"));

		internal static Texture2D CultivateSquare => _cultivateSquare ?? (_cultivateSquare = LoadTexture("cultivate_v2_square.png"));

		internal static Texture2D CultivatePath => _cultivatePath ?? (_cultivatePath = LoadTexture("cultivate_v2_path.png"));

		internal static Texture2D CultivatePathSquare => _cultivatePathSquare ?? (_cultivatePathSquare = LoadTexture("cultivate_v2_path_square.png"));

		internal static Texture2D RaiseSquare => _raiseSquare ?? (_raiseSquare = LoadTexture("raise_v2_square.png"));

		internal static Texture2D Lower => _lower ?? (_lower = LoadTexture("lower_v2.png"));

		private static Texture2D LoadTexture(string fileName)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_0098: Expected O, but got Unknown
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith("." + fileName, StringComparison.OrdinalIgnoreCase) || name.EndsWith(fileName, StringComparison.OrdinalIgnoreCase));
			if (text == null)
			{
				TerrainLog.LogWarning("Embedded texture not found: " + fileName);
				return new Texture2D(2, 2);
			}
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				TerrainLog.LogWarning("Could not open embedded stream: " + text);
				return new Texture2D(2, 2);
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			LoadImageViaReflection(val, memoryStream.ToArray());
			return val;
		}

		private static void LoadImageViaReflection(Texture2D tex, byte[] data)
		{
			if (s_loadImageMethod == null)
			{
				s_loadImageMethod = (Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? Type.GetType("UnityEngine.ImageConversion, UnityEngine"))?.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				});
			}
			s_loadImageMethod?.Invoke(null, new object[2] { tex, data });
		}

		internal static Sprite CreateSprite(Texture2D texture)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f));
		}
	}
	public class Overlay
	{
		private Particle[] particles = (Particle[])(object)new Particle[2];

		private GameObject GameObject { get; }

		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_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				int num = ps.GetParticles(particles, particles.Length);
				if (num <= 0)
				{
					return StartColor;
				}
				return Color32.op_Implicit(((Particle)(ref particles[Mathf.Min(1, num - 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_000a: Unknown result type (might be due to invalid IL or missing references)
				MainModule val = psm;
				((MainModule)(ref val)).startColor = MinMaxGradient.op_Implicit(value);
			}
		}

		public Vector3 LocalScale
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return Transform.localScale;
			}
			set
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				Transform.localScale = 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_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_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				MainModule val = psm;
				MinMaxCurve startSize = ((MainModule)(ref val)).startSize;
				if (!Mathf.Approximately(((MinMaxCurve)(ref startSize)).constant, value))
				{
					MainModule main = ps.main;
					((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(value);
					if (particles.Length < ps.particleCount)
					{
						particles = (Particle[])(object)new Particle[ps.particleCount];
					}
					int num = ps.GetParticles(particles, particles.Length);
					for (int i = 0; i < num; i++)
					{
						((Particle)(ref particles[i])).startSize = value;
					}
					if (num > 0)
					{
						ps.SetParticles(particles, num);
					}
				}
			}
		}

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

		protected Overlay? secondary;

		protected Overlay? tertiary;

		protected HoverInfo? hoverInfo;

		private readonly List<Heightmap> heightmaps = new List<Heightmap>();

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

		private void Update()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (primary == null)
			{
				Transform val = ((Component)this).transform.Find("_GhostOnly");
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				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 = Color.white;
				primary.Enabled = false;
				secondary.Enabled = false;
				tertiary.Enabled = false;
				Initialize();
			}
			OnRefresh();
		}

		protected abstract void Initialize();

		protected abstract void OnRefresh();

		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 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 SnapToPaintGrid(Overlay core, Overlay feather)
		{
			//IL_0011: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			heightmaps.Clear();
			Heightmap.FindHeightmap(((Component)this).transform.position, 1f, heightmaps);
			if (heightmaps.Count == 0)
			{
				core.LocalPosition = VerticalOffset;
				feather.LocalPosition = VerticalOffset;
				return;
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(float.PositiveInfinity, float.PositiveInfinity);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(float.NegativeInfinity, float.NegativeInfinity);
			float num = 0f;
			foreach (Heightmap heightmap in heightmaps)
			{
				if (PreciseTerrainModifier.TryGetPaintMaskWorldBounds(heightmap, ((Component)this).transform.position, 1, out var min, out var max))
				{
					val = Vector2.Min(val, min);
					val2 = Vector2.Max(val2, max);
					num = Mathf.Max(num, heightmap.m_scale);
				}
			}
			if (float.IsPositiveInfinity(val.x))
			{
				core.LocalPosition = VerticalOffset;
				feather.LocalPosition = VerticalOffset;
			}
			else
			{
				SetBounds(core, val - Vector2.one * num, val2 + Vector2.one * num);
				SetBounds(feather, val - Vector2.one * num * 2f, val2 + Vector2.one * num * 2f);
			}
		}

		private void SetBounds(Overlay overlay, Vector2 min, Vector2 max)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0070: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = max - min;
			float num = (overlay.StartSize = Mathf.Max(val.x, val.y));
			overlay.LocalScale = new Vector3(val.x / num, 1f, val.y / num);
			overlay.Position = new Vector3((min.x + max.x) * 0.5f, ((Component)this).transform.position.y + VerticalOffset.y, (min.y + max.y) * 0.5f);
		}
	}
	public abstract class HoverInfoEnabled : OverlayVisualizer
	{
		protected override void Initialize()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (hoverInfo != null && secondary != null)
			{
				hoverInfo.Color = secondary.StartColor;
			}
		}

		protected override void OnRefresh()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (hoverInfo != null)
			{
				hoverInfo.Enabled = TerrainConfig.EnableHoverInfo.Value;
				if (hoverInfo.Enabled)
				{
					hoverInfo.RotateToPlayer();
					Vector3 position = ((Component)this).transform.position;
					hoverInfo.Text = $"x: {position.x:0}, y: {position.y:0.000}, z: {position.z:0}";
				}
			}
		}
	}
	public class LevelGroundOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeRecoloringBounds(secondary);
				VisualizeRecoloringBounds(tertiary);
				tertiary.StartColor = new Color(1f, 1f, 1f, 0.3f);
			}
		}

		protected override void OnRefresh()
		{
			if (secondary != null && tertiary != null && primary != null)
			{
				SnapToPaintGrid(secondary, tertiary);
				base.OnRefresh();
				primary.Enabled = false;
				secondary.Enabled = true;
				tertiary.Enabled = true;
			}
		}
	}
	public class RaiseGroundOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeTerraformingBounds(secondary);
				VisualizeTerraformingBounds(tertiary);
				secondary.LocalScale = Vector3.one;
				tertiary.LocalScale = Vector3.one;
			}
		}

		protected override void OnRefresh()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			if (secondary == null || tertiary == null || primary == null)
			{
				return;
			}
			Heightmap val = Heightmap.FindHeightmap(((Component)this).transform.position);
			float num = (Object.op_Implicit((Object)(object)val) ? val.m_scale : 1f);
			TerrainOp component = ((Component)this).GetComponent<TerrainOp>();
			float num2 = PreciseRaiseMath.SlopePivot(Object.op_Implicit((Object)(object)component) ? HardnessModifier.CurrentRaisePower(component.m_settings.m_raisePower) : 1f);
			secondary.StartSize = Mathf.Max(0.1f, 2f * num2 * num);
			tertiary.StartSize = 4f * num;
			base.OnRefresh();
			primary.Enabled = false;
			secondary.Enabled = true;
			GroundLevelSpinner.Refresh();
			Vector3 localPosition = secondary.LocalPosition;
			localPosition.y = OverlayVisualizer.VerticalOffset.y + GroundLevelSpinner.Value;
			secondary.LocalPosition = localPosition;
			Vector3 val2 = secondary.Position - OverlayVisualizer.VerticalOffset;
			if (hoverInfo != null)
			{
				if (GroundLevelSpinner.Value > 0f)
				{
					float value = GroundLevelSpinner.Value;
					hoverInfo.Text = $"x: {val2.x:0}, y: {val2.y - value:0.000}, z: {val2.z:0}\n\nh: +{value:0.000}";
				}
				else
				{
					hoverInfo.Text = $"x: {val2.x:0}, y: {val2.y:0.000}, z: {val2.z:0}";
				}
			}
			tertiary.Enabled = true;
		}
	}
	public class SquarePathOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeRecoloringBounds(secondary);
				VisualizeRecoloringBounds(tertiary);
				tertiary.StartColor = new Color(1f, 1f, 1f, 0.3f);
			}
		}

		protected override void OnRefresh()
		{
			if (secondary != null && tertiary != null && primary != null)
			{
				SnapToPaintGrid(secondary, tertiary);
				base.OnRefresh();
				primary.Enabled = false;
				secondary.Enabled = true;
				tertiary.Enabled = true;
			}
		}
	}
	public class CultivateOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeRecoloringBounds(secondary);
				VisualizeRecoloringBounds(tertiary);
				tertiary.StartColor = new Color(1f, 1f, 1f, 0.3f);
			}
		}

		protected override void OnRefresh()
		{
			if (secondary != null && tertiary != null && primary != null)
			{
				SnapToPaintGrid(secondary, tertiary);
				base.OnRefresh();
				primary.Enabled = false;
				secondary.Enabled = true;
				tertiary.Enabled = true;
			}
		}
	}
	public class SeedGrassOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeRecoloringBounds(secondary);
				VisualizeRecoloringBounds(tertiary);
				tertiary.StartColor = new Color(1f, 1f, 1f, 0.3f);
			}
		}

		protected override void OnRefresh()
		{
			if (secondary != null && tertiary != null && primary != null)
			{
				SnapToPaintGrid(secondary, tertiary);
				base.OnRefresh();
				primary.Enabled = false;
				secondary.Enabled = true;
				tertiary.Enabled = true;
			}
		}
	}
	public class RemoveModificationsOverlayVisualizer : HoverInfoEnabled
	{
		protected override void Initialize()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			base.Initialize();
			if (secondary != null && tertiary != null)
			{
				Freeze(secondary);
				Freeze(tertiary);
				VisualizeTerraformingBounds(secondary);
				VisualizeTerraformingBounds(tertiary);
				secondary.StartColor = new Color(1f, 0.2f, 0.2f, 0.8f);
				tertiary.StartColor = new Color(1f, 0.2f, 0.2f, 0.3f);
			}
		}

		internal void SetScale(Vector3 scale)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (secondary != null)
			{
				secondary.LocalScale = scale;
			}
			if (tertiary != null)
			{
				tertiary.LocalScale = scale;
			}
		}

		protected override void OnRefresh()
		{
			if (secondary != null && tertiary != null && primary != null)
			{
				base.OnRefresh();
				primary.Enabled = false;
				secondary.Enabled = true;
				tertiary.Enabled = true;
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "SetInvalidPlacementHeightlight")]
	public static class OverlayVisualizationRedshiftHeigthlightBlocker
	{
		private static bool Prefix(Piece __instance)
		{
			return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInChildren<OverlayVisualizer>());
		}
	}
	internal static class PaintGridMath
	{
		internal static float TexelCenterUv(int index, int terrainWidth)
		{
			return ((float)index + 0.5f) / ((float)terrainWidth + 1f);
		}

		internal static void GetAxisIndices(int terrainWidth, int centerIndex, int radius, out int first, out int last)
		{
			first = Math.Max(0, centerIndex - radius);
			last = Math.Min(terrainWidth, centerIndex + radius);
		}

		internal static bool TryGetAxisBounds(int terrainWidth, float vertexScale, float zoneCenter, int firstPaintedTexel, int lastPaintedTexel, out float min, out float max)
		{
			if (firstPaintedTexel > lastPaintedTexel)
			{
				min = 0f;
				max = 0f;
				return false;
			}
			float num = (float)terrainWidth * vertexScale * 0.5f;
			float num2 = zoneCenter - num;
			min = num2 + (float)firstPaintedTexel * vertexScale;
			max = num2 + (float)lastPaintedTexel * vertexScale;
			return true;
		}
	}
	internal static class PreciseRaiseMath
	{
		internal const int ModifiedRadius = 1;

		internal const int InfluenceRadius = 2;

		internal const float MinPower = 0.05f;

		internal const float MaxPower = 1f;

		internal static bool TryGetTargetHeight(float tileHeight, float refHeight, float delta, float weight, out float targetHeight)
		{
			targetHeight = refHeight + delta;
			if (delta < 0f && targetHeight > tileHeight)
			{
				return false;
			}
			if (delta >= 0f)
			{
				if (targetHeight < tileHeight)
				{
					return false;
				}
				if (targetHeight > tileHeight + delta)
				{
					targetHeight = tileHeight + delta;
				}
			}
			if (weight < 1f)
			{
				targetHeight = tileHeight + (targetHeight - tileHeight) * weight;
			}
			return true;
		}

		internal static float Weight(int dx, int dz, float power)
		{
			int num = Math.Max(Math.Abs(dx), Math.Abs(dz));
			if (num >= 2)
			{
				return 0f;
			}
			float num2 = SlopePivot(power);
			if ((float)num <= num2)
			{
				return 1f;
			}
			return (float)(2 - num) / (2f - num2);
		}

		internal static float SlopePivot(float power)
		{
			power = (float.IsNaN(power) ? 1f : Math.Max(0.05f, Math.Min(1f, power)));
			float num = (1f - power) / 0.95f;
			return 1f * num;
		}
	}
	[HarmonyPatch]
	public static class PreciseTerrainModifier
	{
		public const int FixedRadius = 1;

		public const int FixedPaintRadius = 1;

		private const int SettingsPayloadMagic = 1096043859;

		private const int SettingsPayloadVersion = 1;

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

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ClutterSystem), "ResetGrass")]
		private static void ResetGrassPrefix(ClutterSystem __instance, Vector3 center, ref float radius)
		{
			if (IsPrecisionModifier(radius))
			{
				radius = 1f;
			}
		}

		[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))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.m_nview) && !__instance.m_nview.IsOwner())
			{
				__instance.m_nview.ClaimOwnership();
			}
			if (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))
			{
				OverlayVisualizer component = ((Component)__instance).gameObject.GetComponent<OverlayVisualizer>();
				if (component is RemoveModificationsOverlayVisualizer)
				{
					__result = Mathf.Max(__result, __instance.m_settings.m_levelRadius + 1f);
				}
				else if (component is RaiseGroundOverlayVisualizer)
				{
					__result = Mathf.Max(__result, 2f);
				}
				else if (Object.op_Implicit((Object)(object)component) && __instance.m_settings.m_paintCleared)
				{
					__result = Mathf.Max(__result, 1f);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "GetRadius")]
		private static void GetSettingsRadiusPostfix(Settings __instance, ref float __result)
		{
			if (__instance.m_raise && IsPrecisionModifier(__instance.m_raiseRadius))
			{
				__result = Mathf.Max(__result, 2f);
			}
			if ((__instance.m_smooth && IsPrecisionModifier(__instance.m_smoothRadius)) || (__instance.m_paintCleared && IsPrecisionModifier(__instance.m_paintRadius)))
			{
				__result = Mathf.Max(__result, 1f);
			}
		}

		private static void RemoveLegacyTerrainModifiers(Vector3 position, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			List<TerrainModifier> list = new List<TerrainModifier>();
			TerrainModifier.GetModifiers(position, radius + 1f, list, (TerrainModifier)null);
			foreach (TerrainModifier item in list)
			{
				if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.m_nview) && !Object.op_Implicit((Object)(object)((Component)item).GetComponentInParent<Piece>()) && !Object.op_Implicit((Object)(object)((Component)item).GetComponentInParent<WearNTear>()))
				{
					item.m_nview.ClaimOwnership();
					ZNetScene.instance.Destroy(((Component)item).gameObject);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Serialize")]
		private static void SerializeSettingsPostfix(Settings __instance, ZPackage pkg)
		{
			if (__instance != null && pkg != null)
			{
				pkg.Write(1096043859);
				pkg.Write(1);
				pkg.Write(__instance.m_levelRadius);
				pkg.Write(__instance.m_raiseRadius);
				pkg.Write(__instance.m_raisePower);
				pkg.Write(__instance.m_raiseDelta);
				pkg.Write(__instance.m_smoothRadius);
				pkg.Write(__instance.m_smoothPower);
				pkg.Write(__instance.m_paintRadius);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Deserialize")]
		private static void DeserializeSettingsPostfix(ZPackage pkg, ref Settings __result)
		{
			if (__result != null && pkg != null && pkg.Size() - pkg.GetPos() >= 36)
			{
				int pos = pkg.GetPos();
				if (pkg.ReadInt() != 1096043859 || pkg.ReadInt() != 1)
				{
					pkg.SetPos(pos);
					return;
				}
				Settings val = CopySettings(__result);
				val.m_levelRadius = pkg.ReadSingle();
				val.m_raiseRadius = pkg.ReadSingle();
				val.m_raisePower = pkg.ReadSingle();
				val.m_raiseDelta = pkg.ReadSingle();
				val.m_smoothRadius = pkg.ReadSingle();
				val.m_smoothPower = pkg.ReadSingle();
				val.m_paintRadius = pkg.ReadSingle();
				__result = val;
			}
		}

		private static Settings CopySettings(Settings source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			return new Settings
			{
				m_levelOffset = source.m_levelOffset,
				m_level = source.m_level,
				m_levelRadius = source.m_levelRadius,
				m_square = source.m_square,
				m_raise = source.m_raise,
				m_raiseRadius = source.m_raiseRadius,
				m_raisePower = source.m_raisePower,
				m_raiseDelta = source.m_raiseDelta,
				m_smooth = source.m_smooth,
				m_smoothRadius = source.m_smoothRadius,
				m_smoothPower = source.m_smoothPower,
				m_paintCleared = source.m_paintCleared,
				m_paintHeightCheck = source.m_paintHeightCheck,
				m_paintType = source.m_paintType,
				m_paintRadius = source.m_paintRadius,
				m_paintStrength = source.m_paintStrength,
				m_paintExp = source.m_paintExp,
				m_paintCurve = source.m_paintCurve,
				m_rotation = source.m_rotation,
				m_sides = source.m_sides,
				m_addMedianMax = source.m_addMedianMax,
				m_centerMultiplicationFactor = source.m_centerMultiplicationFactor,
				m_pointMultiplicationFactor = source.m_pointMultiplicationFactor,
				m_halfOffset = source.m_halfOffset
			};
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPrefix(TerrainComp __instance, Vector3 pos, Settings modifier)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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)
			{
				int num = Mathf.Clamp(Mathf.RoundToInt(modifier.m_levelRadius), 1, Mathf.CeilToInt(TerrainConfig.MaxRadius.Value));
				RemoveLegacyTerrainModifiers(pos, num);
				RemoveTerrainModifications(__instance, pos, num);
				PreciseRecolorTerrain(__instance, pos, (PaintType)3, heightCheck: false, num);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private static void InternalDoOperationPostfix(TerrainComp __instance)
		{
			if (IsPrecisionModifier(__instance.m_lastOpRadius))
			{
				__instance.m_lastOpRadius = 1f;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "SmoothTerrain")]
		private static bool PreciseSmoothTerrain(TerrainComp __instance, Vector3 worldPos, float radius)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPrecisionModifier(radius))
			{
				return true;
			}
			int num = __instance.m_width + 1;
			int x = default(int);
			int x2 = default(int);
			__instance.m_hmap.WorldToVertex(worldPos, ref x, ref x2);
			float num2 = worldPos.y - ((Component)__instance).transform.position.y;
			FindExtrema(x, num, out var xMin, out var xMax);
			FindExtrema(x2, num, out var xMin2, out var xMax2);
			for (int i = xMin; i <= xMax; i++)
			{
				for (int j = xMin2; j <= xMax2; j++)
				{
					int num3 = j * num + i;
					float height = __instance.m_hmap.GetHeight(i, j);
					float num4 = num2 - height;
					float num5 = __instance.m_smoothDelta[num3];
					__instance.m_smoothDelta[num3] = Mathf.Clamp(num5 + num4, -1f, 1f);
					__instance.m_modifiedHeight[num3] = true;
				}
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")]
		private static bool RaiseTerrainPrefix(TerrainComp __instance, Vector3 worldPos, float radius, float delta, float power)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPrecisionModifier(radius))
			{
				return true;
			}
			int num = __instance.m_width + 1;
			int num2 = default(int);
			int num3 = default(int);
			__instance.m_hmap.WorldToVertex(worldPos, ref num2, ref num3);
			float refHeight = worldPos.y - ((Component)__instance).transform.position.y;
			FindExtrema(num2, num, 1, out var xMin, out var xMax);
			FindExtrema(num3, num, 1, out var xMin2, out var xMax2);
			for (int i = xMin; i <= xMax; i++)
			{
				for (int j = xMin2; j <= xMax2; j++)
				{
					float height = __instance.m_hmap.GetHeight(i, j);
					float weight = PreciseRaiseMath.Weight(i - num2, j - num3, power);
					if (PreciseRaiseMath.TryGetTargetHeight(height, refHeight, delta, weight, out var targetHeight))
					{
						int num4 = j * num + i;
						float num5 = targetHeight - height + __instance.m_smoothDelta[num4];
						__instance.m_smoothDelta[num4] = 0f;
						__instance.m_levelDelta[num4] += num5;
						__instance.m_levelDelta[num4] = Mathf.Clamp(__instance.m_levelDelta[num4], -8f, 8f);
						__instance.m_modifiedHeight[num4] = true;
					}
				}
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "PaintCleared")]
		private static bool PaintClearedPrefix(TerrainComp __instance, Vector3 worldPos, Settings settings)
		{
			//IL_0010: 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)
			if (!IsPrecisionModifier(settings.m_paintRadius))
			{
				return true;
			}
			PreciseRecolorTerrain(__instance, worldPos, settings.m_paintType, settings.m_paintHeightCheck);
			return false;
		}

		public static void RemoveTerrainModifications(TerrainComp comp, Vector3 worldPos, int radius = 1)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			int num = comp.m_width + 1;
			int x = default(int);
			int x2 = default(int);
			comp.m_hmap.WorldToVertex(worldPos, ref x, ref x2);
			FindExtrema(x, num, radius, out var xMin, out var xMax);
			FindExtrema(x2, num, radius, out var xMin2, out var xMax2);
			for (int i = xMin; i <= xMax; i++)
			{
				for (int j = xMin2; j <= xMax2; j++)
				{
					int num2 = j * num + i;
					comp.m_levelDelta[num2] = 0f;
					comp.m_smoothDelta[num2] = 0f;
					comp.m_modifiedHeight[num2] = false;
				}
			}
		}

		public static void PreciseRecolorTerrain(TerrainComp comp, Vector3 worldPos, PaintType paintType, bool heightCheck = false, int radius = 1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Color val = ResolveColor(paintType);
			GetPaintMaskBounds(comp.m_hmap, worldPos, radius, out var xStart, out var xMax, out var yStart, out var yMax);
			int num = comp.m_width + 1;
			for (int i = xStart; i <= xMax; i++)
			{
				for (int j = yStart; j <= yMax; j++)
				{
					val.a = comp.m_hmap.GetPaintMask(i, j).a;
					int num2 = j * num + i;
					comp.m_paintMask[num2] = val;
					comp.m_modifiedPaint[num2] = true;
				}
			}
		}

		public static void GetPaintMaskBounds(Heightmap heightmap, Vector3 worldPos, int radius, out int xStart, out int xMax, out int yStart, out int yMax)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			int centerIndex = default(int);
			int centerIndex2 = default(int);
			heightmap.WorldToVertex(worldPos, ref centerIndex, ref centerIndex2);
			PaintGridMath.GetAxisIndices(heightmap.m_width, centerIndex, radius, out xStart, out xMax);
			PaintGridMath.GetAxisIndices(heightmap.m_width, centerIndex2, radius, out yStart, out yMax);
		}

		public static bool TryGetPaintMaskWorldBounds(Heightmap heightmap, Vector3 worldPos, int radius, out Vector2 min, out Vector2 max)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			GetPaintMaskBounds(heightmap, worldPos, radius, out var xStart, out var xMax, out var yStart, out var yMax);
			float min2;
			float max2;
			bool num = PaintGridMath.TryGetAxisBounds(heightmap.m_width, heightmap.m_scale, ((Component)heightmap).transform.position.x, xStart, xMax, out min2, out max2);
			float min3;
			float max3;
			bool flag = PaintGridMath.TryGetAxisBounds(heightmap.m_width, heightmap.m_scale, ((Component)heightmap).transform.position.z, yStart, yMax, out min3, out max3);
			if (!num || !flag)
			{
				min = default(Vector2);
				max = default(Vector2);
				return false;
			}
			min = new Vector2(min2, min3);
			max = new Vector2(max2, max3);
			return true;
		}

		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)
			return (Color)((int)paintType switch
			{
				0 => Heightmap.m_paintMaskDirt, 
				1 => Heightmap.m_paintMaskCultivated, 
				2 => Heightmap.m_paintMaskPaved, 
				_ => Heightmap.m_paintMaskNothing, 
			});
		}

		public static void FindExtrema(int x, int worldSize, out int xMin, out int xMax)
		{
			FindExtrema(x, worldSize, 1, out xMin, out xMax);
		}

		private static void FindExtrema(int x, int worldSize, int radius, out int xMin, out int xMax)
		{
			PaintGridMath.GetAxisIndices(worldSize - 1, x, radius, out xMin, out xMax);
		}
	}
	[HarmonyPatch]
	internal static class RadiusModifier
	{
		private static bool RadiusToolIsInUse = false;

		private static TerrainOp? activeRadiusTool;

		private static float lastOriginalRadius;

		private static float lastModdedRadius;

		private static float lastTotalDelta;

		private static Vector3 lastGhostScale = Vector3.zero;

		private const float MinRadius = 0.5f;

		private const float Tolerance = 0.01f;

		internal static void Tick(Player __instance)
		{
			//IL_004b: 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())
			{
				SelectRadiusTool(null);
				return;
			}
			if (!IsValidSelectedPiece(__instance, out TerrainOp terrainOp))
			{
				SelectRadiusTool(null);
				return;
			}
			SelectRadiusTool(terrainOp);
			if (ShouldModifyRadius())
			{
				SetRadius(terrainOp, Input.mouseScrollDelta.y * TerrainConfig.RadiusScrollScale.Value);
			}
			RefreshGhostScale(__instance);
		}

		private static void SelectRadiusTool(TerrainOp? terrainOp)
		{
			//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)
			if (!((Object)(object)activeRadiusTool == (Object)(object)terrainOp))
			{
				activeRadiusTool = terrainOp;
				RadiusToolIsInUse = false;
				lastOriginalRadius = 0f;
				lastModdedRadius = 0f;
				lastTotalDelta = 0f;
				lastGhostScale = Vector3.zero;
			}
		}

		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))
			{
				terrainOp = null;
				return false;
			}
			OverlayVisualizer component = ((Component)selectedPiece).gameObject.GetComponent<OverlayVisualizer>();
			if (Object.op_Implicit((Object)(object)component) && !(component is RemoveModificationsOverlayVisualizer))
			{
				terrainOp = null;
				return false;
			}
			terrainOp = ((Component)selectedPiece).gameObject.GetComponent<TerrainOp>();
			return (Object)(object)terrainOp != (Object)null;
		}

		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 (TerrainConfig.EnableRadiusModifier.Value && Input.GetKey(TerrainConfig.RadiusKey.Value))
			{
				return Input.mouseScrollDelta.y != 0f;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPriority(700)]
		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		private static void AwakePrefix(TerrainOp __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)((Component)__instance).gameObject))
			{
				return;
			}
			OverlayVisualizer component = ((Component)__instance).gameObject.GetComponent<OverlayVisualizer>();
			bool flag = component is RemoveModificationsOverlayVisualizer;
			if (!Object.op_Implicit((Object)(object)component) || flag)
			{
				if (flag)
				{
					__instance.m_settings.m_levelRadius = ModifyRadius(__instance.m_settings.m_levelRadius, lastTotalDelta);
				}
				if (__instance.m_settings.m_level)
				{
					__instance.m_settings.m_levelRadius = ModifyRadius(__instance.m_settings.m_levelRadius, lastTotalDelta);
				}
				if (__instance.m_settings.m_raise)
				{
					__instance.m_settings.m_raiseRadius = ModifyRadius(__instance.m_settings.m_raiseRadius, lastTotalDelta);
				}
				if (__instance.m_settings.m_smooth)
				{
					__instance.m_settings.m_smoothRadius = ModifyRadius(__instance.m_settings.m_smoothRadius, lastTotalDelta);
				}
				if (__instance.m_settings.m_paintCleared)
				{
					__instance.m_settings.m_paintRadius = ModifyRadius(__instance.m_settings.m_paintRadius, lastTotalDelta);
				}
			}
		}

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

		private static void SetRadius(TerrainOp terrainOp, float delta)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)terrainOp) && Object.op_Implicit((Object)(object)((Component)terrainOp).gameObject.GetComponent<RemoveModificationsOverlayVisualizer>()))
			{
				delta = Mathf.Sign(delta);
			}
			if (!RadiusToolIsInUse && Object.op_Implicit((Object)(object)terrainOp))
			{
				if (TryGetMaximumRadius(terrainOp, out var maxRadius))
				{
					RadiusToolIsInUse = true;
					lastOriginalRadius = maxRadius;
					lastModdedRadius = ModifyRadius(maxRadius, delta);
					lastTotalDelta += lastModdedRadius - maxRadius;
				}
			}
			else
			{
				float num = lastModdedRadius;
				lastModdedRadius = ModifyRadius(lastModdedRadius, delta);
				lastTotalDelta += lastModdedRadius - num;
			}
			if (lastOriginalRadius > 0.001f)
			{
				lastGhostScale = new Vector3(lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius, lastModdedRadius / lastOriginalRadius);
			}
		}

		private static void RefreshGhostScale(Player player)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (!RadiusToolIsInUse || !Object.op_Implicit((Object)(object)player.m_placementGhost))
			{
				return;
			}
			RemoveModificationsOverlayVisualizer component = player.m_placementGhost.GetComponent<RemoveModificationsOverlayVisualizer>();
			if (Object.op_Implicit((Object)(object)component))
			{
				TerrainOp component2 = player.m_placementGhost.GetComponent<TerrainOp>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.m_settings.m_levelRadius = lastModdedRadius;
				}
				component.SetScale(lastGhostScale);
				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)
				{
					((Component)componentInChildren).transform.localScale = lastGhostScale;
				}
			}
		}

		private static bool TryGetMaximumRadius(TerrainOp terrainOp, out float maxRadius)
		{
			maxRadius = 0f;
			if (Object.op_Implicit((Object)(object)((Component)terrainOp).gameObject.GetComponent<RemoveModificationsOverlayVisualizer>()))
			{
				maxRadius = terrainOp.m_settings.m_levelRadius;
			}
			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;
		}
	}
	internal static class TerrainConfig
	{
		internal static ConfigEntry<bool> EnableRadiusModifier;

		internal static ConfigEntry<KeyCode> RadiusKey;

		internal static ConfigEntry<float> RadiusScrollScale;

		internal static ConfigEntry<float> MaxRadius;

		internal static ConfigEntry<bool> EnableHardnessModifier;

		internal static ConfigEntry<KeyCode> HardnessKey;

		internal static ConfigEntry<float> HardnessScrollScale;

		internal static ConfigEntry<bool> EnableHoverInfo;

		internal static ConfigEntry<bool> EnableTerrainSynergy;

		internal static ConfigEntry<bool> EnableSquareTools;

		internal static ConfigEntry<bool> EnablePrecisionRaise;

		internal static ConfigEntry<bool> EnableLowerGround;

		internal static ConfigEntry<bool> EnableRemoveModifications;

		internal static ConfigEntry<TerrainLog.InfoLevel> Verbosity;

		internal static void Init(ConfigFile config, ConfigSync configSync)
		{
			EnableRadiusModifier = Bind(config, configSync, "Terrain - Radius", "Enable Radius Modifier", value: true, "Permite alterar o raio das ferramentas de terreno usando Scroll do mouse.", synchronized: false);
			RadiusKey = Bind<KeyCode>(config, configSync, "Terrain - Radius", "Radius Key", (KeyCode)308, "Tecla para segurar enquanto usa a roda do mouse para alterar o raio.", synchronized: false);
			RadiusScrollScale = Bind(config, configSync, "Terrain - Radius", "Radius Scroll Scale", 0.5f, "Sensibilidade da mudanca de raio com o scroll.", synchronized: false);
			MaxRadius = Bind(config, configSync, "Terrain - Radius", "Max Radius", 10f, "Raio maximo permitido para ferramentas de terreno.");
			EnableHardnessModifier = Bind(config, configSync, "Terrain - Hardness", "Enable Hardness Modifier", value: true, "Permite alterar a dureza/sharpness das ferramentas de terreno com scroll.", synchronized: false);
			HardnessKey = Bind<KeyCode>(config, configSync, "Terrain - Hardness", "Hardness Key", (KeyCode)304, "Tecla para segurar enquanto usa a roda do mouse para alterar a dureza.", synchronized: false);
			HardnessScrollScale = Bind(config, configSync, "Terrain - Hardness", "Hardness Scroll Scale", 0.5f, "Sensibilidade da mudanca de dureza com o scroll.", synchronized: false);
			EnableHoverInfo = Bind(config, configSync, "Terrain - Interface", "Enable Hover Info", value: true, "Exibe informacoes de coordenadas e altura na ferramenta.", synchronized: false);
			EnableTerrainSynergy = Bind(config, configSync, "Terrain - Synergy", "Enable Terrain Building Synergy", value: true, "Terraplanar concede XP de Construcao e gasta menos vigor de acordo com a habilidade de Construcao.");
			EnableSquareTools = Bind(config, configSync, "Terrain - Tools", "Enable Square Tools", value: true, "Ativa as ferramentas de terreno no formato quadrado alinhadas ao grid do mundo.");
			EnablePrecisionRaise = Bind(config, configSync, "Terrain - Tools", "Enable Precision Raise", value: true, "Ativa a ferramenta de elevacao precisa com controle de altura no scroll.");
			EnableLowerGround = Bind(config, configSync, "Terrain - Tools", "Enable Lower Ground", value: true, "Ativa o modo de rebaixar terreno na enxada.");
			EnableRemoveModifications = Bind(config, configSync, "Terrain - Tools", "Enable Remove Modifications", value: true, "Ativa a ferramenta de restaurar terreno natural original.");
			Verbosity = Bind(config, configSync, "Terrain - Debug", "Verbosity", TerrainLog.InfoLevel.Low, "Nivel de detalhes no log de terreno.", synchronized: false);
		}

		private static ConfigEntry<T> Bind<T>(ConfigFile config, ConfigSync configSync, string group, string name, T value, string description, bool synchronized = true)
		{
			ConfigEntry<T> val = config.Bind<T>(group, name, value, description);
			configSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronized;
			return val;
		}
	}
	internal static class TerrainLog
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource? logSource;

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

		internal static void LogInfo(string message, InfoLevel level = InfoLevel.Low)
		{
			if (TerrainConfig.Verbosity == null || TerrainConfig.Verbosity.Value >= level)
			{
				ManualLogSource? obj = logSource;
				if (obj != null)
				{
					obj.LogInfo((object)message);
				}
			}
		}

		internal static void LogWarning(string message)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogWarning((object)message);
			}
		}

		internal static void LogError(string message)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogError((object)message);
			}
		}

		internal static void LogDebug(string message)
		{
			ManualLogSource? obj = logSource;
			if (obj != null)
			{
				obj.LogDebug((object)message);
			}
		}
	}
	[HarmonyPatch]
	internal static class TerrainPieceManager
	{
		private class ToolDef
		{
			public string name;

			public string basePrefab;

			public string nameToken;

			public string descToken;

			public Func<Texture2D> iconGetter;

			public bool isHoe;

			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 bool invertGhost;

			public Requirement[]? requirements;

			public ToolDef(string name, string basePrefab, string nameToken, string descToken, Func<Texture2D> iconGetter, bool isHoe, 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, bool invertGhost = false, Requirement[]? requirements = null)
			{
				this.name = name;
				this.basePrefab = basePrefab;
				this.nameToken = nameToken;
				this.descToken = descToken;
				this.iconGetter = iconGetter;
				this.isHoe = isHoe;
				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.invertGhost = invertGhost;
				this.requirements = requirements;
			}
		}

		private static bool piecesCreated = false;

		private static readonly List<GameObject> createdToolPrefabs = new List<GameObject>();

		private static readonly Dictionary<string, GameObject> toolRefs = new Dictionary<string, GameObject>();

		private static readonly List<ToolDef> tools = new List<ToolDef>
		{
			new ToolDef("mud_road_v2_sq", "mud_road_v2", "$atmc_level_square_name", "$atmc_level_square_desc", () => IconCache.MudRoadSquare, isHoe: true, typeof(LevelGroundOverlayVisualizer)),
			new ToolDef("raise_v2_precise", "raise_v2", "$atmc_raise_precision_name", "$atmc_raise_precision_desc", () => IconCache.RaiseSquare, isHoe: true, typeof(RaiseGroundOverlayVisualizer)),
			new ToolDef("lower_v2", "raise_v2", "$atmc_lower_name", "$atmc_lower_desc", () => IconCache.Lower, isHoe: true, null, null, null, null, 1.5f, 0.5f, -0.5f, null, null, null, null, null, invertGhost: true, Array.Empty<Requirement>()),
			new ToolDef("path_v2_square", "path_v2", "$atmc_path_square_name", "$atmc_path_square_desc", () => IconCache.MudRoadPathSquare, isHoe: true, typeof(SquarePathOverlayVisualizer)),
			new ToolDef("paved_road_v2_square", "paved_road_v2", "$atmc_paved_square_name", "$atmc_paved_square_desc", () => IconCache.PavedRoadSquare, isHoe: true, typeof(SquarePathOverlayVisualizer)),
			new ToolDef("paved_road_v2_path", "paved_road_v2", "$atmc_paved_path_name", "$atmc_paved_path_desc", () => IconCache.PavedRoadPath, isHoe: true, null, null, null, null, null, null, null, false),
			new ToolDef("paved_road_v2_path_square", "paved_road_v2", "$atmc_paved_path_square_name", "$atmc_paved_path_square_desc", () => IconCache.PavedRoadPathSquare, isHoe: true, typeof(SquarePathOverlayVisualizer), null, null, null, null, null, null, false),
			new ToolDef("remove_terrain_mods", "mud_road_v2", "$atmc_remove_name", "$atmc_remove_desc", () => IconCache.Remove, isHoe: true, typeof(RemoveModificationsOverlayVisualizer), false, 1f, false, null, null, null, false, null, null, false),
			new ToolDef("cultivate_v2_square", "cultivate_v2", "$atmc_cultivate_square_name", "$atmc_cultivate_square_desc", () => IconCache.CultivateSquare, isHoe: false, typeof(CultivateOverlayVisualizer)),
			new ToolDef("cultivate_v2_path", "cultivate_v2", "$atmc_cultivate_path_name", "$atmc_cultivate_path_desc", () => IconCache.CultivatePath, isHoe: false, null, null, null, null, null, null, null, false),
			new ToolDef("cultivate_v2_path_square", "cultivate_v2", "$atmc_cultivate_path_square_name", "$atmc_cultivate_path_square_desc", () => IconCache.CultivatePathSquare, isHoe: false, typeof(CultivateOverlayVisualizer), null, null, null, null, null, null, false),
			new ToolDef("replant_v2_square", "replant_v2", "$atmc_replant_square_name", "$atmc_replant_square_desc", () => IconCache.ReplantSquare, isHoe: false, typeof(SeedGrassOverlayVisualizer))
		};

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private static void SetupLanguagePostfix(Localization __instance)
		{
			string selectedLanguage = __instance.GetSelectedLanguage();
			bool isPortuguese = selectedLanguage.Equals("Portuguese_Brazilian", StringComparison.OrdinalIgnoreCase) || selectedLanguage.Equals("Portuguese", StringComparison.OrdinalIgnoreCase);
			Add("atmc_level_square_name", "Nivelar terreno (quadrado)", "Level ground (square)");
			Add("atmc_level_square_desc", "Nivela o terreno alinhado ao grid do mundo com base na sua posição. Use Shift + clique para nivelar da posição apontada (suaviza o solo).", "Levels ground to the world grid based on player position. Use Shift + click to level from the pointed position instead (this smooths the terrain).");
			Add("atmc_raise_precision_name", "Elevar terreno (precisão)", "Raise ground (precision)");
			Add("atmc_raise_precision_desc", "Eleva o terreno mi