Decompiled source of ESvK TerrainAdjuster v0.3.0

BepInEx/plugins/ESvK_TerrainAdjuster/ESvK_TerrainAdjuster.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ESvK.TerrainAdjuster.Config;
using ESvK.TerrainAdjuster.Pieces;
using ESvK.TerrainAdjuster.Terrain;
using ESvK.TerrainAdjuster.UI;
using ESvK.TerrainAdjuster.Utilities;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ESvK Terrain Adjuster")]
[assembly: AssemblyDescription("Original vanilla Hoe extension with Super Flat")]
[assembly: AssemblyFileVersion("0.3.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1")]
[assembly: AssemblyVersion("0.3.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ESvK.TerrainAdjuster
{
	[BepInPlugin("esvk.valheim.terrainadjuster", "ESvK Terrain Adjuster", "0.3.0")]
	[BepInDependency("com.jotunn.jotunn", "2.30.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "esvk.valheim.terrainadjuster";

		public const string Name = "ESvK Terrain Adjuster";

		public const string Version = "0.3.0";

		private Harmony patches;

		private bool registered;

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Log.Initialize(((BaseUnityPlugin)this).Logger);
			ModConfig.Initialize(((BaseUnityPlugin)this).Config);
			TerrainBrush.Reset();
			patches = new Harmony("esvk.valheim.terrainadjuster");
			patches.PatchAll(typeof(Plugin).Assembly);
			PrefabManager.OnVanillaPrefabsAvailable += RegisterContent;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ESvK Terrain Adjuster 0.3.0 loaded: Harmony patches installed; waiting for vanilla prefabs.");
		}

		private void RegisterContent()
		{
			if (registered)
			{
				return;
			}
			try
			{
				TerrainTool.Register();
				registered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"ESvK tool, native Hoe menu, Super Flat and Restore Terrain registered.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("ESvK registration failed: " + ex));
			}
		}

		private void Update()
		{
			EquippedSpeed.Update();
			RestoreTerrainAction.UpdateSelection();
			if (registered)
			{
				TerrainMenu.RefreshSettings();
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					TerrainTool.RefreshLocalSettings();
					TerrainBrush.Update();
				}
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent;
			Harmony obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}
namespace ESvK.TerrainAdjuster.Utilities
{
	internal static class BorderedIcon
	{
		internal static Sprite Create(Sprite source)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)source) || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return source;
			}
			Rect textureRect = source.textureRect;
			int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source.texture).width, ((Texture)source.texture).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			Texture2D val = null;
			try
			{
				Graphics.Blit((Texture)(object)source.texture, temporary);
				RenderTexture.active = temporary;
				val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(textureRect, 0, 0);
				val.Apply();
				int num3 = Mathf.Max(3, Mathf.RoundToInt((float)Mathf.Min(num, num2) * 0.06f));
				Texture2D val2 = new Texture2D(num + num3 * 2, num2 + num3 * 2, (TextureFormat)4, false);
				((Object)val2).name = "ESvK_SuperFlat_RuntimeBorder";
				((Texture)val2).wrapMode = (TextureWrapMode)1;
				Color[] array = (Color[])(object)new Color[((Texture)val2).width * ((Texture)val2).height];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = new Color(1f, 0f, 0.75f, 1f);
				}
				val2.SetPixels(array);
				val2.SetPixels(num3, num3, num, num2, val.GetPixels());
				val2.Apply(false, true);
				return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), source.pixelsPerUnit);
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	internal static class DevelopmentIcon
	{
		internal static Sprite Create()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			((Object)val).name = "ESvK_OriginalDevelopmentIcon";
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = (float)j - 31.5f;
					float num2 = (float)i - 31.5f;
					bool num3 = num * num + num2 * num2 < 900f;
					Color val2 = (Color)(num3 ? new Color(0.035f, 0.11f, 0.13f, 1f) : Color.clear);
					float num4 = (float)i - 6f * Mathf.Sin((float)j * 0.09f);
					if (num3 && j > 9 && j < 54 && i > 10 && i < 54 && Mathf.Repeat(num4, 10f) < 2f)
					{
						((Color)(ref val2))..ctor(0.3f, 0.88f, 0.68f, 1f);
					}
					if (num3 && ((j >= 29 && j <= 33 && i > 12 && i < 52) || (j > 23 && j < 40 && i > 34 && i < 40)))
					{
						((Color)(ref val2))..ctor(1f, 0.72f, 0.25f, 1f);
					}
					array[i * 64 + j] = val2;
				}
			}
			val.SetPixels(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
		}
	}
	[HarmonyPatch]
	internal static class EquippedSpeed
	{
		private static bool previousEquipped;

		private static bool previousBoost;

		private static float previousMultiplier;

		internal static bool Holding(Player player)
		{
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting())
			{
				return TerrainTool.IsEquipped(player);
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(SEMan), "ApplyStatusEffectSpeedMods")]
		private static void Apply(Character ___m_character, ref float speed)
		{
			Player val = (Player)(object)((___m_character is Player) ? ___m_character : null);
			if (val != null && Holding(val) && ModConfig.EnableEquippedSpeedBoost.Value)
			{
				speed *= ModConfig.EquippedSpeedMultiplier.Value;
			}
		}

		internal static void Update()
		{
			bool flag = Holding(Player.m_localPlayer);
			bool flag2 = flag && ModConfig.EnableEquippedSpeedBoost.Value;
			if (flag != previousEquipped)
			{
				Log.Debug(flag ? "Tool equipped" : "Tool unequipped");
			}
			if (flag2 != previousBoost || (flag2 && previousMultiplier != ModConfig.EquippedSpeedMultiplier.Value))
			{
				Log.Debug(flag2 ? ("Equipped speed boost applied: x" + ModConfig.EquippedSpeedMultiplier.Value) : "Equipped speed boost removed");
			}
			previousEquipped = flag;
			previousBoost = flag2;
			previousMultiplier = ModConfig.EquippedSpeedMultiplier.Value;
		}
	}
	internal static class Log
	{
		private static ManualLogSource source;

		internal static void Initialize(ManualLogSource logger)
		{
			source = logger;
		}

		internal static void Error(string message)
		{
			source.LogError((object)("[ESvK Terrain] " + message));
		}

		internal static void Warn(string message)
		{
			source.LogWarning((object)("[ESvK Terrain] " + message));
		}

		internal static void Debug(string message)
		{
			if (ModConfig.DebugLogging.Value)
			{
				source.LogInfo((object)("[ESvK Terrain] " + message));
			}
		}
	}
	internal static class RestoreIcon
	{
		internal static Sprite Create()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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_00e0: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			((Object)val).name = "ESvK_Restore_Original_R";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			Color[] array = (Color[])(object)new Color[4096];
			string[] array2 = new string[7] { "11110", "10001", "10001", "11110", "10100", "10010", "10001" };
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					Color val2 = ((j < 4 || j >= 60 || i < 4 || i >= 60) ? new Color(0.62f, 0.2f, 1f, 1f) : (((float)i < 19f + 4f * Mathf.Sin((float)j * 0.13f)) ? new Color(0.13f, 0.21f, 0.17f, 1f) : new Color(0.06f, 0.08f, 0.12f, 1f)));
					int index = (j - 17) / 6;
					int num = (52 - i) / 6;
					if (j >= 17 && j < 47 && i > 10 && i <= 52 && num < 7 && array2[num][index] == '1')
					{
						((Color)(ref val2))..ctor(0.94f, 0.9f, 1f, 1f);
					}
					array[i * 64 + j] = val2;
				}
			}
			val.SetPixels(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
		}
	}
}
namespace ESvK.TerrainAdjuster.UI
{
	internal static class RadiusDisplay
	{
		internal static void Show(float radius)
		{
			if (Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				MessageHud.instance.ShowMessage((MessageType)2, "Super Flat Radius: " + radius.ToString("0.#", CultureInfo.InvariantCulture) + "m", 0, (Sprite)null, false, true);
				Log.Debug("Super Flat radius=" + radius.ToString(CultureInfo.InvariantCulture));
			}
		}
	}
}
namespace ESvK.TerrainAdjuster.Pieces
{
	[HarmonyPatch]
	internal static class RestoreActionCost
	{
		private sealed class CostState
		{
			internal SharedData Data;

			internal float Stamina;

			internal bool Durability;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static void BeforePlacement(Player __instance, out CostState __state)
		{
			__state = null;
			if (!TerrainTool.IsEquipped(__instance))
			{
				return;
			}
			Piece selectedPiece = __instance.GetSelectedPiece();
			if (Object.op_Implicit((Object)(object)selectedPiece) && RestoreTerrainAction.IsRestore(((Component)selectedPiece).gameObject))
			{
				ItemData rightItem = ((Humanoid)__instance).RightItem;
				if (rightItem?.m_shared?.m_attack != null)
				{
					__state = new CostState
					{
						Data = rightItem.m_shared,
						Stamina = rightItem.m_shared.m_attack.m_attackStamina,
						Durability = rightItem.m_shared.m_useDurability
					};
					rightItem.m_shared.m_attack.m_attackStamina = 0f;
					rightItem.m_shared.m_useDurability = false;
				}
			}
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static void AfterPlacement(CostState __state)
		{
			if (__state != null)
			{
				__state.Data.m_attack.m_attackStamina = __state.Stamina;
				__state.Data.m_useDurability = __state.Durability;
			}
		}
	}
	[HarmonyPatch]
	internal static class RestoreTerrainAction
	{
		internal const string PrefabName = "ESvK_TerrainAdjuster_RestoreTerrain";

		private static bool wasSelected;

		internal static TerrainOp Operation { get; private set; }

		internal static bool IsRestore(GameObject prefab)
		{
			if (Object.op_Implicit((Object)(object)prefab))
			{
				return Utils.GetPrefabName(((Object)prefab).name) == "ESvK_TerrainAdjuster_RestoreTerrain";
			}
			return false;
		}

		internal static void Register(PieceTable table, GameObject superFlatPrefab)
		{
			PrefabManager instance = PrefabManager.Instance;
			GameObject val = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_RestoreTerrain", superFlatPrefab);
			if (!Object.op_Implicit((Object)(object)val) || val.activeInHierarchy)
			{
				throw new InvalidOperationException("Restore Terrain needs an inactive native template.");
			}
			Piece component = val.GetComponent<Piece>();
			component.m_name = "Restore Terrain";
			component.m_description = "Restore terrain within the selected radius to its original state.";
			component.m_icon = RestoreIcon.Create();
			component.m_resources = Array.Empty<Requirement>();
			component.m_craftingStation = null;
			component.m_allowAltGroundPlacement = false;
			Operation = val.GetComponent<TerrainOp>();
			Operation.m_settings = RestoreTerrainNetworking.NewSettings(TerrainBrush.EffectiveRadius);
			Operation.m_spawnOnPlaced = null;
			instance.AddPrefab(val);
			table.m_pieces.Add(val);
			RegisterOperation(ObjectDB.instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")]
		private static void RegisterOperation(ObjectDB __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)Operation))
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode("ESvK_TerrainAdjuster_RestoreTerrain");
				if (__instance.m_terrainOpsByHash.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)Operation)
				{
					throw new InvalidOperationException("Restore Terrain prefab hash collision.");
				}
				if (!__instance.m_terrainOps.Contains(Operation))
				{
					__instance.m_terrainOps.Add(Operation);
				}
				__instance.m_terrainOpsByHash[stableHashCode] = Operation;
			}
		}

		internal static void UpdateSelection()
		{
			Player localPlayer = Player.m_localPlayer;
			Piece val = ((Object.op_Implicit((Object)(object)localPlayer) && TerrainTool.IsEquipped(localPlayer)) ? localPlayer.GetSelectedPiece() : null);
			int num;
			if (Object.op_Implicit((Object)(object)val))
			{
				num = (IsRestore(((Component)val).gameObject) ? 1 : 0);
				if (num != 0 && !wasSelected)
				{
					Log.Debug("Restore Terrain selected");
				}
			}
			else
			{
				num = 0;
			}
			wasSelected = (byte)num != 0;
		}
	}
	[HarmonyPatch]
	internal static class TerrainMenu
	{
		internal const string TableName = "ESvK_TerrainAdjuster_Table";

		internal const string SuperFlatName = "ESvK_TerrainAdjuster_SuperFlat";

		private static Piece superFlat;

		private static Requirement[] paidRequirements;

		private static CraftingStation workbench;

		internal static TerrainOp Operation { get; private set; }

		internal static PieceTable Register(Sprite fallbackIcon)
		{
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Expected O, but got Unknown
			PrefabManager instance = PrefabManager.Instance;
			PieceTable buildPieces = instance.GetPrefab("Hoe").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			if (!Object.op_Implicit((Object)(object)buildPieces) || buildPieces.m_pieces.Count == 0)
			{
				throw new InvalidOperationException("Current Hoe table is missing.");
			}
			GameObject val = ((IEnumerable<GameObject>)buildPieces.m_pieces).FirstOrDefault((Func<GameObject, bool>)IsLevelingTemplate);
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("No native leveling/smoothing template found. Hoe entries: " + string.Join("; ", buildPieces.m_pieces.Select(DescribeTemplate)));
			}
			GameObject val2 = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_Table", ((Component)buildPieces).gameObject);
			PieceTable component = val2.GetComponent<PieceTable>();
			component.m_pieces = new List<GameObject>(buildPieces.m_pieces);
			component.m_categories = new List<PieceCategory>(buildPieces.m_categories);
			component.m_categoryLabels = new List<string>(buildPieces.m_categoryLabels);
			instance.AddPrefab(val2);
			GameObject val3 = instance.CreateClonedPrefab("ESvK_TerrainAdjuster_SuperFlat", val);
			superFlat = val3.GetComponent<Piece>();
			superFlat.m_name = "Super Flat";
			superFlat.m_description = "Flatten the full circle to your standing level. Hold Shift for aimed height. Ctrl + wheel adjusts radius.";
			superFlat.m_enabled = true;
			superFlat.m_groundPiece = true;
			superFlat.m_allowAltGroundPlacement = true;
			superFlat.m_canBeRemoved = false;
			superFlat.m_icon = BorderedIcon.Create(val.GetComponent<Piece>().m_icon) ?? fallbackIcon;
			Operation = val3.GetComponent<TerrainOp>();
			if (!Object.op_Implicit((Object)(object)Operation))
			{
				if (val3.activeInHierarchy)
				{
					throw new InvalidOperationException("Super Flat template must be inactive during registration.");
				}
				TerrainModifier component2 = val3.GetComponent<TerrainModifier>();
				Operation = val3.AddComponent<TerrainOp>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					Operation.m_onPlacedEffect = component2.m_onPlacedEffect;
				}
				ZNetView component3 = val3.GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					Object.DestroyImmediate((Object)(object)component3);
				}
			}
			Operation.m_settings = SuperFlatNetworking.NewSettings(ModConfig.DefaultRadius.Value);
			Operation.m_spawnOnPlaced = null;
			SuperFlatPreview.Configure(val3);
			TerrainModifier[] components = val3.GetComponents<TerrainModifier>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			paidRequirements = (Requirement[])(object)new Requirement[1]
			{
				new Requirement
				{
					m_resItem = instance.GetPrefab("Stone").GetComponent<ItemDrop>(),
					m_amount = 2,
					m_recover = false
				}
			};
			workbench = instance.GetPrefab("piece_workbench").GetComponent<CraftingStation>();
			RefreshSettings();
			instance.AddPrefab(val3);
			component.m_pieces.Add(val3);
			RegisterOperation(ObjectDB.instance);
			RestoreTerrainAction.Register(component, val3);
			Log.Debug("Copied " + buildPieces.m_pieces.Count + " native Hoe entries; appended Super Flat and Restore Terrain. Leveling template: " + ((Object)val).name);
			return component;
		}

		internal static bool IsSuperFlat(GameObject prefab)
		{
			if (Object.op_Implicit((Object)(object)prefab))
			{
				return Utils.GetPrefabName(((Object)prefab).name) == "ESvK_TerrainAdjuster_SuperFlat";
			}
			return false;
		}

		private static bool IsLevelingTemplate(GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>()))
			{
				return false;
			}
			TerrainOp component = prefab.GetComponent<TerrainOp>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (component.m_settings != null)
				{
					if (!component.m_settings.m_level)
					{
						return component.m_settings.m_smooth;
					}
					return true;
				}
				return false;
			}
			TerrainModifier component2 = prefab.GetComponent<TerrainModifier>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				if (!component2.m_level)
				{
					return component2.m_smooth;
				}
				return true;
			}
			return false;
		}

		private static string DescribeTemplate(GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return "<missing>";
			}
			TerrainOp component = prefab.GetComponent<TerrainOp>();
			TerrainModifier component2 = prefab.GetComponent<TerrainModifier>();
			return ((Object)prefab).name + " TerrainOp=" + Object.op_Implicit((Object)(object)component) + " level=" + (Object.op_Implicit((Object)(object)component) && component.m_settings != null && component.m_settings.m_level) + " smooth=" + (Object.op_Implicit((Object)(object)component) && component.m_settings != null && component.m_settings.m_smooth) + " TerrainModifier=" + Object.op_Implicit((Object)(object)component2);
		}

		internal static void RefreshSettings()
		{
			if (Object.op_Implicit((Object)(object)superFlat))
			{
				superFlat.m_resources = (ModConfig.RequiresResources.Value ? paidRequirements : Array.Empty<Requirement>());
				superFlat.m_craftingStation = (ModConfig.RequireWorkbench.Value ? workbench : null);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ObjectDB), "UpdateRegisters")]
		private static void RegisterOperation(ObjectDB __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)Operation))
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode("ESvK_TerrainAdjuster_SuperFlat");
				if (__instance.m_terrainOpsByHash.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)Operation)
				{
					throw new InvalidOperationException("Super Flat TerrainOp hash collision.");
				}
				if (!__instance.m_terrainOps.Contains(Operation))
				{
					__instance.m_terrainOps.Add(Operation);
				}
				__instance.m_terrainOpsByHash[stableHashCode] = Operation;
			}
		}
	}
	internal static class TerrainTool
	{
		internal const string PrefabName = "ESvK_TerrainAdjuster";

		private const string DisplayName = "ESvK Terrain Adjuster";

		private static CustomItem tool;

		private static Recipe recipe;

		private static float vanillaStamina;

		private static float vanillaDrain;

		internal static bool IsEquipped(Player player)
		{
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && Object.op_Implicit((Object)(object)player.GetBuildTool()))
			{
				return ((Object)player.GetBuildTool()).name == "ESvK_TerrainAdjuster_Table";
			}
			return false;
		}

		internal static void Register()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			Sprite val = DevelopmentIcon.Create();
			PieceTable buildPieces = TerrainMenu.Register(val);
			tool = new CustomItem("ESvK_TerrainAdjuster", "Hoe");
			if (!Object.op_Implicit((Object)(object)tool.ItemPrefab))
			{
				throw new InvalidOperationException("Vanilla Hoe prefab unavailable.");
			}
			SharedData shared = tool.ItemDrop.m_itemData.m_shared;
			SharedData shared2 = PrefabManager.Instance.GetPrefab("Hoe").GetComponent<ItemDrop>().m_itemData.m_shared;
			if (shared == shared2 || shared.m_attack == shared2.m_attack)
			{
				throw new InvalidOperationException("Vanilla hoe clone did not isolate mutable item settings.");
			}
			vanillaStamina = shared.m_attack.m_attackStamina;
			vanillaDrain = shared.m_useDurabilityDrain;
			shared.m_name = "ESvK Terrain Adjuster";
			shared.m_description = "Vanilla Hoe tools plus Super Flat. Hold Ctrl and scroll to adjust Super Flat radius.";
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
			shared.m_buildPieces = buildPieces;
			shared.m_maxQuality = 1;
			shared.m_equipStatusEffect = null;
			tool.ItemDrop.m_itemData.m_dropPrefab = tool.ItemPrefab;
			recipe = ScriptableObject.CreateInstance<Recipe>();
			((Object)recipe).name = "Recipe_ESvK_TerrainAdjuster";
			recipe.m_item = tool.ItemDrop;
			recipe.m_amount = 1;
			recipe.m_enabled = true;
			recipe.m_minStationLevel = 1;
			recipe.m_resources = Array.Empty<Requirement>();
			tool.Recipe = new CustomRecipe(recipe, false, false);
			ApplyItemSettings(shared);
			if (!ItemManager.Instance.AddItem(tool))
			{
				throw new InvalidOperationException("Could not register ESvK tool.");
			}
			Log.Debug("Vanilla Hoe cloned at runtime; standalone ESvK tool and recipe registered.");
		}

		private static void ApplyItemSettings(SharedData data)
		{
			data.m_useDurability = ModConfig.UseDurability.Value;
			data.m_useDurabilityDrain = (ModConfig.UseDurability.Value ? vanillaDrain : 0f);
			data.m_attack.m_attackStamina = (ModConfig.UseStamina.Value ? vanillaStamina : 0f);
		}

		internal static void RefreshLocalSettings()
		{
			if (tool == null)
			{
				return;
			}
			ApplyItemSettings(tool.ItemDrop.m_itemData.m_shared);
			foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems())
			{
				if (allItem.m_shared.m_name == "ESvK Terrain Adjuster")
				{
					ApplyItemSettings(allItem.m_shared);
				}
			}
		}
	}
}
namespace ESvK.TerrainAdjuster.Terrain
{
	internal static class FlatGrid
	{
		internal static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		internal static int Apply(int width, float scale, float originX, float originZ, float centerX, float centerZ, float targetLocalY, float radius, float[] baseline, float[] level, float[] smooth, bool[] modified, bool[] mask)
		{
			int num = width + 1;
			int num2 = num * num;
			int num3 = 0;
			if (baseline.Length != num2 || level.Length != num2 || smooth.Length != num2 || modified.Length != num2 || mask.Length != num2)
			{
				throw new ArgumentException("Terrain grid size mismatch.");
			}
			if (!Finite(targetLocalY) || !Finite(radius) || radius <= 0f || !Finite(scale) || scale <= 0f)
			{
				throw new ArgumentException("Invalid terrain grid parameters.");
			}
			for (int i = 0; i <= width; i++)
			{
				for (int j = 0; j <= width; j++)
				{
					float num4 = originX + (float)j * scale - centerX;
					float num5 = originZ + (float)i * scale - centerZ;
					if (!(num4 * num4 + num5 * num5 > radius * radius + 0.0001f))
					{
						int num6 = i * num + j;
						level[num6] = targetLocalY - baseline[num6];
						smooth[num6] = 0f;
						modified[num6] = (mask[num6] = true);
						num3++;
					}
				}
			}
			return num3;
		}

		internal static byte[] Encode(bool[] mask)
		{
			using MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write(1);
			binaryWriter.Write(mask.Length);
			for (int i = 0; i < mask.Length; i += 8)
			{
				byte b = 0;
				for (int j = 0; j < 8 && i + j < mask.Length; j++)
				{
					if (mask[i + j])
					{
						b |= (byte)(1 << j);
					}
				}
				binaryWriter.Write(b);
			}
			return memoryStream.ToArray();
		}

		internal static bool[] Decode(byte[] bytes, int count)
		{
			if (bytes == null || bytes.Length == 0)
			{
				return null;
			}
			if (count < 1 || bytes.Length != 8 + (count + 7) / 8)
			{
				throw new InvalidDataException("Invalid Super Flat mask length.");
			}
			using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes));
			if (binaryReader.ReadInt32() != 1 || binaryReader.ReadInt32() != count)
			{
				throw new InvalidDataException("Unsupported Super Flat mask version/grid.");
			}
			bool[] array = new bool[count];
			for (int i = 0; i < count; i += 8)
			{
				byte b = binaryReader.ReadByte();
				for (int j = 0; j < 8 && i + j < count; j++)
				{
					array[i + j] = (b & (1 << j)) != 0;
				}
			}
			return array;
		}
	}
	internal static class PreviewRadiusMath
	{
		internal static float Diameter(float radius)
		{
			return radius * 2f;
		}
	}
	internal static class RadiusMath
	{
		internal static float Clamp(float value, float minimum, float maximum)
		{
			if (float.IsNaN(minimum) || float.IsInfinity(minimum))
			{
				minimum = 1f;
			}
			if (float.IsNaN(maximum) || float.IsInfinity(maximum))
			{
				maximum = 20f;
			}
			minimum = Math.Max(0.1f, minimum);
			maximum = Math.Max(minimum, maximum);
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				value = minimum;
			}
			return Math.Max(minimum, Math.Min(maximum, value));
		}
	}
	internal static class RestoreGrid
	{
		internal static List<int> Select(int width, float scale, float originX, float originZ, float centerX, float centerZ, float radius)
		{
			if (width < 1 || width > 1024 || !Finite(scale) || scale <= 0f || !Finite(radius) || radius < 1f || radius > 20f || !Finite(originX) || !Finite(originZ) || !Finite(centerX) || !Finite(centerZ))
			{
				throw new ArgumentException("Invalid restore grid or radius.");
			}
			List<int> list = new List<int>();
			int num = width + 1;
			for (int i = 0; i <= width; i++)
			{
				for (int j = 0; j <= width; j++)
				{
					float num2 = originX + (float)j * scale - centerX;
					float num3 = originZ + (float)i * scale - centerZ;
					if (num2 * num2 + num3 * num3 <= radius * radius)
					{
						list.Add(i * num + j);
					}
				}
			}
			return list;
		}

		internal static void Clear(List<int> indices, float[] level, float[] smooth, bool[] height, bool[] paint, bool[] flatMask, out int heights, out int paints)
		{
			int num = level.Length;
			if (smooth.Length != num || height.Length != num || paint.Length != num || (flatMask != null && flatMask.Length != num))
			{
				throw new ArgumentException("Restore array mismatch.");
			}
			foreach (int index in indices)
			{
				if (index < 0 || index >= num)
				{
					throw new ArgumentOutOfRangeException("indices");
				}
			}
			heights = (paints = 0);
			foreach (int index2 in indices)
			{
				if (height[index2] || level[index2] != 0f || smooth[index2] != 0f || (flatMask != null && flatMask[index2]))
				{
					heights++;
				}
				if (paint[index2])
				{
					paints++;
				}
				level[index2] = (smooth[index2] = 0f);
				height[index2] = (paint[index2] = false);
				if (flatMask != null)
				{
					flatMask[index2] = false;
				}
			}
		}

		private static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class RestoreTerrainExecution
	{
		private static readonly int FlatMaskKey = StringExtensionMethods.GetStableHashCode("esvk.terrainadjuster.flatmask.v1");

		private static readonly FieldRef<Heightmap, HMBuildData> BuildData = AccessTools.FieldRefAccess<Heightmap, HMBuildData>("m_buildData");

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private unsafe static bool Apply(Settings modifier, Vector3 pos, Heightmap ___m_hmap, ZNetView ___m_nview, bool ___m_initialized, float[] ___m_levelDelta, float[] ___m_smoothDelta, bool[] ___m_modifiedHeight, bool[] ___m_modifiedPaint, Color[] ___m_paintMask, ref int ___m_operations, ref Vector3 ___m_lastOpPoint, ref float ___m_lastOpRadius)
		{
			//IL_0031: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			if (!RestoreTerrainNetworking.TryGet(modifier, out var request))
			{
				return true;
			}
			try
			{
				if (!___m_initialized || !Object.op_Implicit((Object)(object)___m_hmap) || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner() || !FlatGrid.Finite(pos.x) || !FlatGrid.Finite(pos.y) || !FlatGrid.Finite(pos.z))
				{
					throw new InvalidOperationException("Missing initialized Heightmap/owned terrain ZDO or invalid center.");
				}
				___m_hmap.Poke(0, false);
				HMBuildData val = BuildData.Invoke(___m_hmap);
				int width = ___m_hmap.m_width;
				int num = (width + 1) * (width + 1);
				if (val == null || val.m_baseHeights == null || val.m_baseMask == null || val.m_baseHeights.Count != num || val.m_baseMask.Length != num || ___m_levelDelta.Length != num || ___m_paintMask.Length != num)
				{
					throw new InvalidOperationException("Original generated height/paint grid unavailable; restoration skipped.");
				}
				float scale = ___m_hmap.m_scale;
				Vector3 position = ((Component)___m_hmap).transform.position;
				float originX = position.x - (float)width * scale * 0.5f;
				float originZ = position.z - (float)width * scale * 0.5f;
				List<int> list = RestoreGrid.Select(width, scale, originX, originZ, pos.x, pos.z, modifier.m_levelRadius);
				request.Skipped = ExcludeLegacy(list, width, scale, originX, originZ);
				if (request.Skipped > 0)
				{
					Log.Warn("Restore Terrain: skipped " + request.Skipped + " vertices overlapping legacy player TerrainModifier state. No legacy objects were removed or converted.");
				}
				bool[] array = FlatGrid.Decode(___m_nview.GetZDO().GetByteArray(FlatMaskKey, (byte[])null), num);
				RestoreGrid.Clear(list, ___m_levelDelta, ___m_smoothDelta, ___m_modifiedHeight, ___m_modifiedPaint, array, out request.Heights, out request.Paint);
				foreach (int item in list)
				{
					___m_paintMask[item] = val.m_baseMask[item];
				}
				if (array != null)
				{
					___m_nview.GetZDO().Set(FlatMaskKey, FlatGrid.Encode(array));
				}
				___m_hmap.Poke(0, false);
				foreach (int item2 in list)
				{
					___m_paintMask[item2] = ___m_hmap.GetPaintMask(item2 % (width + 1), item2 / (width + 1));
				}
				___m_operations++;
				___m_lastOpPoint = pos;
				___m_lastOpRadius = modifier.m_levelRadius;
				request.Applied = true;
				string[] obj = new string[8]
				{
					"Terrain vertices restored: ",
					request.Heights.ToString(),
					"; Terrain paint restored: ",
					request.Paint.ToString(),
					"; Heightmap=",
					null,
					null,
					null
				};
				Vector3 val2 = position;
				obj[5] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString();
				obj[6] = "; legacy vertices skipped=";
				obj[7] = request.Skipped.ToString();
				Log.Debug(string.Concat(obj));
			}
			catch (Exception ex)
			{
				Log.Error("Restore Terrain skipped/failed: " + ex);
			}
			return false;
		}

		private static int ExcludeLegacy(List<int> indices, int width, float scale, float originX, float originZ)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			int count = indices.Count;
			foreach (TerrainModifier allInstance in TerrainModifier.GetAllInstances())
			{
				if (Object.op_Implicit((Object)(object)allInstance) && ((Behaviour)allInstance).enabled && ((Component)allInstance).gameObject.activeInHierarchy && allInstance.m_playerModifiction && (allInstance.m_level || allInstance.m_smooth || allInstance.m_paintCleared))
				{
					Vector3 center = ((Component)allInstance).transform.position;
					float extent = allInstance.GetRadius() * Mathf.Sqrt(2f) + scale;
					indices.RemoveAll(delegate(int i)
					{
						float num = originX + (float)(i % (width + 1)) * scale - center.x;
						float num2 = originZ + (float)(i / (width + 1)) * scale - center.z;
						return num * num + num2 * num2 <= extent * extent;
					});
				}
			}
			return count - indices.Count;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "DoOperation")]
		private static void Completed(Settings modifier, ZNetView ___m_nview)
		{
			if (RestoreTerrainNetworking.TryGet(modifier, out var request) && request.Applied)
			{
				Log.Debug("Restore operation completed: native terrain save returned; ZDO revision=" + ___m_nview.GetZDO().DataRevision + "; vertices=" + request.Heights + "; paint=" + request.Paint);
			}
		}
	}
	[HarmonyPatch]
	internal static class RestoreTerrainNetworking
	{
		internal sealed class Request
		{
			internal bool Applied;

			internal int Heights;

			internal int Paint;

			internal int Skipped;
		}

		private const int Protocol = 1163067905;

		private static readonly ConditionalWeakTable<Settings, Request> requests = new ConditionalWeakTable<Settings, Request>();

		internal static bool TryGet(Settings settings, out Request request)
		{
			request = null;
			if (settings != null)
			{
				return requests.TryGetValue(settings, out request);
			}
			return false;
		}

		internal static Settings NewSettings(float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0036: 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_0049: Expected O, but got Unknown
			return new Settings
			{
				m_level = true,
				m_levelRadius = radius,
				m_square = false,
				m_raise = false,
				m_smooth = false,
				m_paintCleared = false,
				m_rotation = false,
				m_levelOffset = 0f,
				m_halfOffset = false
			};
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		private static void BeforeRestoreAwake(TerrainOp __instance)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance) && !TerrainOp.m_forceDisableTerrainOps && RestoreTerrainAction.IsRestore(((Component)__instance).gameObject))
			{
				float effectiveRadius = TerrainBrush.EffectiveRadius;
				__instance.m_settings = NewSettings(effectiveRadius);
				List<Heightmap> list = new List<Heightmap>();
				Heightmap.FindHeightmap(((Component)__instance).transform.position, effectiveRadius, list);
				Log.Debug("Restore center: " + ((object)((Component)__instance).transform.position/*cast due to .constrained prefix*/).ToString() + "; Restore radius: " + effectiveRadius + "; Heightmaps affected: " + list.Count);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Serialize")]
		private static void Serialize(Settings __instance, ZPackage pkg, GameObject prefab)
		{
			if (RestoreTerrainAction.IsRestore(prefab))
			{
				pkg.Write(1163067905);
				pkg.Write(__instance.m_levelRadius);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Deserialize")]
		private static void Deserialize(ZPackage pkg, ref Settings __result)
		{
			if (!Object.op_Implicit((Object)(object)RestoreTerrainAction.Operation) || __result != RestoreTerrainAction.Operation.m_settings)
			{
				return;
			}
			try
			{
				if (pkg.ReadInt() != 1163067905)
				{
					throw new InvalidOperationException("Unsupported restore RPC version.");
				}
				float num = pkg.ReadSingle();
				if (!FlatGrid.Finite(num) || num < 1f || num > 20f)
				{
					throw new InvalidOperationException("Invalid restore radius.");
				}
				num = RadiusMath.Clamp(num, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value);
				__result = NewSettings(num);
				requests.Add(__result, new Request());
				Log.Debug("Restore Terrain RPC received; radius=" + num);
			}
			catch (Exception ex)
			{
				__result = null;
				Log.Error("Restore Terrain RPC rejected: " + ex.Message);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
		private static void Sent(TerrainOp modifier)
		{
			if (Object.op_Implicit((Object)(object)modifier) && RestoreTerrainAction.IsRestore(((Component)modifier).gameObject))
			{
				Log.Debug("Restore Terrain RPC sent to terrain owner.");
			}
		}
	}
	[HarmonyPatch]
	internal static class SuperFlatNetworking
	{
		private sealed class Marker
		{
		}

		private const int Protocol = 1163067649;

		private static readonly ConditionalWeakTable<Settings, Marker> received = new ConditionalWeakTable<Settings, Marker>();

		internal static bool IsReceived(Settings settings)
		{
			Marker value;
			if (settings != null)
			{
				return received.TryGetValue(settings, out value);
			}
			return false;
		}

		internal static Settings NewSettings(float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			return new Settings
			{
				m_level = true,
				m_levelRadius = radius,
				m_levelOffset = 0f,
				m_square = false,
				m_raise = false,
				m_smooth = false,
				m_paintCleared = false,
				m_rotation = false,
				m_halfOffset = false
			};
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainOp), "Awake")]
		private static void BeforeTerrainOpAwake(TerrainOp __instance)
		{
			//IL_0045: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance) && !TerrainOp.m_forceDisableTerrainOps && TerrainMenu.IsSuperFlat(((Component)__instance).gameObject))
			{
				float effectiveRadius = TerrainBrush.EffectiveRadius;
				__instance.m_settings = NewSettings(effectiveRadius);
				Log.Debug("Super Flat target position: " + ((object)((Component)__instance).transform.position/*cast due to .constrained prefix*/).ToString() + "; target height: " + ((Component)__instance).transform.position.y + "; radius: " + effectiveRadius);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Serialize")]
		private static void Serialize(Settings __instance, ZPackage pkg, GameObject prefab)
		{
			if (TerrainMenu.IsSuperFlat(prefab))
			{
				pkg.Write(1163067649);
				pkg.Write(__instance.m_levelRadius);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Settings), "Deserialize")]
		private static void Deserialize(ZPackage pkg, ref Settings __result)
		{
			if (!Object.op_Implicit((Object)(object)TerrainMenu.Operation) || __result != TerrainMenu.Operation.m_settings)
			{
				return;
			}
			try
			{
				if (pkg.ReadInt() != 1163067649)
				{
					throw new InvalidOperationException("Unsupported Super Flat RPC version.");
				}
				float num = pkg.ReadSingle();
				if (!FlatGrid.Finite(num) || num < 1f || num > 20f)
				{
					throw new InvalidOperationException("Invalid Super Flat RPC radius.");
				}
				num = RadiusMath.Clamp(num, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value);
				__result = NewSettings(num);
				received.Add(__result, new Marker());
				Log.Debug("Terrain RPC received: Super Flat radius=" + num);
			}
			catch (Exception ex)
			{
				__result = null;
				Log.Error("Super Flat RPC rejected: " + ex.Message);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
		private static void Sent(TerrainOp modifier, ZNetView ___m_nview, Heightmap ___m_hmap)
		{
			if (Object.op_Implicit((Object)(object)modifier) && TerrainMenu.IsSuperFlat(((Component)modifier).gameObject))
			{
				Log.Debug("Terrain RPC sent: RPC_ApplyOperation; Heightmap=" + Object.op_Implicit((Object)(object)___m_hmap) + "; TerrainComp/ZDO valid=" + (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsValid()) + "; local owner=" + (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsOwner()));
			}
		}
	}
	internal static class SuperFlatPreview
	{
		internal static void Configure(GameObject prefab)
		{
			Transform val = prefab.transform.Find("_GhostOnly");
			if (!Object.op_Implicit((Object)(object)val))
			{
				Log.Error("Super Flat is missing its native _GhostOnly preview.");
			}
			else if (!Object.op_Implicit((Object)(object)((Component)val).GetComponent<NativeHoeRingPreview>()))
			{
				((Component)val).gameObject.AddComponent<NativeHoeRingPreview>();
			}
		}
	}
	internal sealed class NativeHoeRingPreview : MonoBehaviour
	{
		private sealed class Ring
		{
			internal ParticleSystem System;

			internal Particle[] Particles;
		}

		private Ring[] rings;

		private Piece piece;

		private float previousRadius = -1f;

		private void LateUpdate()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)piece))
			{
				piece = ((Component)this).GetComponentInParent<Piece>();
			}
			if (!Object.op_Implicit((Object)(object)piece) || (!TerrainMenu.IsSuperFlat(((Component)piece).gameObject) && !RestoreTerrainAction.IsRestore(((Component)piece).gameObject)) || !Player.IsPlacementGhost(((Component)piece).gameObject))
			{
				return;
			}
			if (rings == null)
			{
				InitializeRings();
			}
			float effectiveRadius = TerrainBrush.EffectiveRadius;
			float num = PreviewRadiusMath.Diameter(effectiveRadius);
			Ring[] array = rings;
			foreach (Ring ring in array)
			{
				ParticleSystem system = ring.System;
				if (Object.op_Implicit((Object)(object)system) && ((Component)system).gameObject.activeInHierarchy)
				{
					MainModule main = system.main;
					((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(num);
					if (!system.isPlaying)
					{
						system.Play(false);
					}
					int particles = system.GetParticles(ring.Particles);
					if (particles == 0)
					{
						system.Emit(1);
						particles = system.GetParticles(ring.Particles);
					}
					for (int j = 0; j < particles; j++)
					{
						((Particle)(ref ring.Particles[j])).startSize = num;
						((Particle)(ref ring.Particles[j])).position = Vector3.zero;
						((Particle)(ref ring.Particles[j])).velocity = Vector3.zero;
					}
					system.SetParticles(ring.Particles, particles);
				}
			}
			if (effectiveRadius != previousRadius)
			{
				Log.Debug("Native particle preview: radius=" + effectiveRadius + "m; diameter=" + num + "m; ring systems=" + rings.Length);
				previousRadius = effectiveRadius;
			}
		}

		private void InitializeRings()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//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_0044: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			List<Ring> list = new List<Ring>();
			ParticleSystem[] componentsInChildren = ((Component)this).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren)
			{
				ParticleSystemRenderer component = ((Component)val).GetComponent<ParticleSystemRenderer>();
				if (Object.op_Implicit((Object)(object)component) && (int)component.renderMode == 2)
				{
					MainModule main = val.main;
					Vector3 val2 = (((int)((MainModule)(ref main)).scalingMode == 0) ? ((Component)val).transform.lossyScale : ((Component)val).transform.localScale);
					MinMaxCurve startSize = ((MainModule)(ref main)).startSize;
					float num = ((MinMaxCurve)(ref startSize)).constantMax * (((int)((MainModule)(ref main)).scalingMode == 2) ? 1f : Mathf.Abs(val2.x));
					string[] obj = new string[6]
					{
						"Measured native ring ",
						((Object)val).name,
						": full-size world radius=",
						(num * 0.5f).ToString(),
						"m; texture=",
						null
					};
					Material sharedMaterial = ((Renderer)component).sharedMaterial;
					object obj2;
					if (sharedMaterial == null)
					{
						obj2 = null;
					}
					else
					{
						Texture mainTexture = sharedMaterial.mainTexture;
						obj2 = ((mainTexture != null) ? ((Object)mainTexture).name : null);
					}
					obj[5] = (string)obj2;
					Log.Debug(string.Concat(obj));
					val.Stop(false, (ParticleSystemStopBehavior)0);
					((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)2;
					((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
					((MainModule)(ref main)).startSize3D = false;
					ShapeModule shape = val.shape;
					((ShapeModule)(ref shape)).enabled = false;
					SizeOverLifetimeModule sizeOverLifetime = val.sizeOverLifetime;
					((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = false;
					SizeBySpeedModule sizeBySpeed = val.sizeBySpeed;
					((SizeBySpeedModule)(ref sizeBySpeed)).enabled = false;
					list.Add(new Ring
					{
						System = val,
						Particles = (Particle[])(object)new Particle[Math.Max(1, ((MainModule)(ref main)).maxParticles)]
					});
				}
			}
			rings = list.ToArray();
			if (rings.Length == 0)
			{
				Log.Error("Super Flat native preview has no horizontal particle ring.");
			}
		}
	}
	[HarmonyPatch]
	internal static class SuperFlatTerrain
	{
		private sealed class State
		{
			internal bool Capture;

			internal float[] Baseline;

			internal bool[] Mask;
		}

		private static readonly int MaskKey = StringExtensionMethods.GetStableHashCode("esvk.terrainadjuster.flatmask.v1");

		private static readonly ConditionalWeakTable<TerrainComp, State> states = new ConditionalWeakTable<TerrainComp, State>();

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
		private static void BeforeRebuild(TerrainComp __instance, List<float> heights, ZNetView ___m_nview, bool ___m_initialized, out float[] __state)
		{
			__state = null;
			if (___m_initialized && Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.IsValid())
			{
				State value = states.GetValue(__instance, (TerrainComp _) => new State());
				try
				{
					value.Mask = FlatGrid.Decode(___m_nview.GetZDO().GetByteArray(MaskKey, (byte[])null), heights.Count);
				}
				catch (Exception ex)
				{
					value.Mask = null;
					Log.Error("Cannot read persistent Super Flat mask: " + ex.Message);
				}
				if (value.Capture || value.Mask != null)
				{
					value.Baseline = heights.ToArray();
				}
				if (value.Mask != null)
				{
					__state = value.Baseline;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
		private static void AfterRebuild(TerrainComp __instance, List<float> heights, float[] ___m_levelDelta, float[] ___m_smoothDelta, float[] __state)
		{
			if (__state == null || !states.TryGetValue(__instance, out var value) || value.Mask == null)
			{
				return;
			}
			for (int i = 0; i < heights.Count; i++)
			{
				if (value.Mask[i])
				{
					heights[i] = __state[i] + ___m_levelDelta[i] + ___m_smoothDelta[i];
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TerrainComp), "InternalDoOperation")]
		private unsafe static bool Apply(TerrainComp __instance, Vector3 pos, Settings modifier, Heightmap ___m_hmap, ZNetView ___m_nview, float[] ___m_levelDelta, float[] ___m_smoothDelta, bool[] ___m_modifiedHeight, ref int ___m_operations, ref Vector3 ___m_lastOpPoint, ref float ___m_lastOpRadius)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			if (!SuperFlatNetworking.IsReceived(modifier))
			{
				return true;
			}
			if (!Object.op_Implicit((Object)(object)___m_hmap) || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner() || !FlatGrid.Finite(pos.x) || !FlatGrid.Finite(pos.y) || !FlatGrid.Finite(pos.z))
			{
				Log.Error("Super Flat rejected: missing Heightmap/owned ZDO or invalid target.");
				return false;
			}
			State value = states.GetValue(__instance, (TerrainComp _) => new State());
			try
			{
				value.Capture = true;
				value.Baseline = null;
				___m_hmap.Poke(0, false);
				if (value.Baseline == null)
				{
					throw new InvalidOperationException("Terrain compiler baseline was not rebuilt.");
				}
				if (value.Mask == null)
				{
					value.Mask = new bool[___m_levelDelta.Length];
				}
				Vector3 position = ((Component)___m_hmap).transform.position;
				float num = (float)___m_hmap.m_width * ___m_hmap.m_scale * 0.5f;
				int num2 = FlatGrid.Apply(___m_hmap.m_width, ___m_hmap.m_scale, position.x - num, position.z - num, pos.x, pos.z, pos.y - position.y, modifier.m_levelRadius, value.Baseline, ___m_levelDelta, ___m_smoothDelta, ___m_modifiedHeight, value.Mask);
				___m_nview.GetZDO().Set(MaskKey, FlatGrid.Encode(value.Mask));
				___m_operations++;
				___m_lastOpPoint = pos;
				___m_lastOpRadius = modifier.m_levelRadius;
				string[] obj = new string[8]
				{
					"Terrain operation applied on owning peer: vertices=",
					num2.ToString(),
					"; Heightmap=",
					null,
					null,
					null,
					null,
					null
				};
				Vector3 val = position;
				obj[3] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
				obj[4] = "; target height=";
				obj[5] = pos.y.ToString();
				obj[6] = "; radius=";
				obj[7] = modifier.m_levelRadius.ToString();
				Log.Debug(string.Concat(obj));
			}
			catch (Exception ex)
			{
				Log.Error("Super Flat operation failed: " + ex);
			}
			finally
			{
				value.Capture = false;
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TerrainComp), "DoOperation")]
		private static void Saved(Settings modifier, ZNetView ___m_nview)
		{
			if (SuperFlatNetworking.IsReceived(modifier))
			{
				Log.Debug("Super Flat native save/refresh returned; ZDO revision=" + ___m_nview.GetZDO().DataRevision);
			}
		}
	}
	[HarmonyPatch]
	internal static class TerrainBrush
	{
		private static bool wasEquipped;

		private static bool wasSuperFlat;

		private static int updatedFrame = -1;

		internal static float Radius { get; private set; }

		internal static float EffectiveRadius => RadiusMath.Clamp(Radius, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value);

		internal static void Reset()
		{
			Radius = ModConfig.DefaultRadius.Value;
		}

		internal static bool CanAdjust()
		{
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && TerrainTool.IsEquipped(localPlayer) && !Console.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !TextInput.IsVisible())
			{
				return !Hud.IsPieceSelectionVisible();
			}
			return false;
		}

		internal static bool ModifierHeld()
		{
			if (!ZInput.GetKey((KeyCode)306, false))
			{
				return ZInput.GetKey((KeyCode)305, false);
			}
			return true;
		}

		internal static void Update()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (updatedFrame == Time.frameCount)
			{
				return;
			}
			updatedFrame = Time.frameCount;
			Radius = EffectiveRadius;
			bool num = TerrainTool.IsEquipped(Player.m_localPlayer);
			if (num && !wasEquipped)
			{
				RadiusDisplay.Show(Radius);
			}
			wasEquipped = num;
			Piece val = (num ? Player.m_localPlayer.GetSelectedPiece() : null);
			int num2;
			if (Object.op_Implicit((Object)(object)val))
			{
				num2 = (TerrainMenu.IsSuperFlat(((Component)val).gameObject) ? 1 : 0);
				if (num2 != 0 && !wasSuperFlat)
				{
					Log.Debug("Super Flat selected");
				}
			}
			else
			{
				num2 = 0;
			}
			wasSuperFlat = (byte)num2 != 0;
			if (CanAdjust() && ModifierHeld() && Mouse.current != null)
			{
				float y = ((InputControl<Vector2>)(object)Mouse.current.scroll).ReadValue().y;
				if (y != 0f)
				{
					Radius = RadiusMath.Clamp(Radius + Mathf.Sign(y) * 1f, ModConfig.MinimumRadius.Value, ModConfig.MaximumRadius.Value);
					RadiusDisplay.Show(Radius);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		private static bool ReserveWheel(ref float __result)
		{
			if (!CanAdjust() || !ModifierHeld())
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
}
namespace ESvK.TerrainAdjuster.Config
{
	internal static class ModConfig
	{
		internal static ConfigEntry<bool> UseStamina;

		internal static ConfigEntry<bool> UseDurability;

		internal static ConfigEntry<bool> RequiresResources;

		internal static ConfigEntry<bool> RequireWorkbench;

		internal static ConfigEntry<bool> DebugLogging;

		internal static ConfigEntry<bool> EnableEquippedSpeedBoost;

		internal static ConfigEntry<float> MinimumRadius;

		internal static ConfigEntry<float> MaximumRadius;

		internal static ConfigEntry<float> DefaultRadius;

		internal static ConfigEntry<float> EquippedSpeedMultiplier;

		internal static void Initialize(ConfigFile config)
		{
			UseStamina = ConfigFileExtensions.BindConfig<bool>(config, "General", "UseStamina", false, "Use vanilla Hoe action stamina costs on the ESvK tool only.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UseDurability = ConfigFileExtensions.BindConfig<bool>(config, "General", "UseDurability", false, "Enable ESvK tool durability.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			RequiresResources = ConfigFileExtensions.BindConfig<bool>(config, "SuperFlat", "RequiresResources", false, "Require two Stone per Super Flat action when enabled. Normal Hoe entries keep their native costs.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			RequireWorkbench = ConfigFileExtensions.BindConfig<bool>(config, "SuperFlat", "RequireWorkbench", false, "Require a workbench for Super Flat when enabled.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f);
			MinimumRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "MinimumRadius", 1f, "Minimum radius in metres.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f);
			MaximumRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "MaximumRadius", 20f, "Maximum radius; minimum wins if the range is reversed.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f);
			DefaultRadius = ConfigFileExtensions.BindConfig<float>(config, "SuperFlat", "DefaultRadius", 5f, "Initial radius, clamped to the allowed range.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableEquippedSpeedBoost = ConfigFileExtensions.BindConfig<bool>(config, "Movement", "EnableEquippedSpeedBoost", true, "Enable movement/sprint boost only while holding the ESvK tool.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f);
			EquippedSpeedMultiplier = ConfigFileExtensions.BindConfig<float>(config, "Movement", "EquippedSpeedMultiplier", 1.35f, "1.35 means +35% speed. Does not change sprint stamina.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			DebugLogging = ConfigFileExtensions.BindConfig<bool>(config, "Debug", "DebugLogging", false, "Local diagnostic logging.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		}
	}
}