Decompiled source of ValAdvancedHoe v0.2.0

BepInEx/plugins/ValAdvancedHoe/ValAdvancedHoe.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValAdvancedHoe")]
[assembly: AssemblyDescription("A configurable Valheim hoe upgrade for large-scale terrain editing.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Matheus Ventura")]
[assembly: AssemblyProduct("ValAdvancedHoe")]
[assembly: AssemblyCopyright("Copyright © 2026 Matheus Ventura")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ccb9dc12-1b44-42ea-a6d6-8a93ad61af6d")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.2.0.0")]
namespace ValAdvancedHoe;

[BepInPlugin("com.vnts.valadvancedhoe", "valAdvancedHoe", "0.2.0")]
[BepInProcess("valheim.exe")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Attack), "SpawnOnHitTerrain")]
	private static class SpawnOnHitTerrainPatch
	{
		private static void Prefix(GameObject prefab, Character character, ItemData weapon, ref float __state)
		{
			HasPendingRaise = (Object)(object)character == (Object)(object)Player.m_localPlayer && IsHoe(weapon);
			PendingRaiseAmount = ((HasPendingRaise && Object.op_Implicit((Object)(object)Instance)) ? Mathf.Max(0.05f, Instance._selectedRaise) : 0f);
			__state = float.NaN;
			if (HasPendingRaise && Object.op_Implicit((Object)(object)prefab))
			{
				TerrainOp val = FindTerrainOperation(prefab);
				if (Object.op_Implicit((Object)(object)val) && val.m_settings != null && val.m_settings.m_raise)
				{
					__state = val.m_settings.m_raiseDelta;
					val.m_settings.m_raiseDelta = PendingRaiseAmount;
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)Localize($"Height sent to terrain: {PendingRaiseAmount:0.##} m", $"Elevação enviada ao terreno: {PendingRaiseAmount:0.##} m"));
				}
			}
		}

		private static void Postfix(GameObject prefab, float __state)
		{
			if (!float.IsNaN(__state) && Object.op_Implicit((Object)(object)prefab))
			{
				TerrainOp val = FindTerrainOperation(prefab);
				if (Object.op_Implicit((Object)(object)val) && val.m_settings != null)
				{
					val.m_settings.m_raiseDelta = __state;
				}
			}
			HasPendingRaise = false;
			PendingRaiseAmount = 0f;
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "ApplyOperation")]
	private static class ApplyTerrainOperationPatch
	{
		private static void Prefix(TerrainComp __instance, TerrainOp modifier)
		{
			if (HasPendingRaise && !((Object)(object)modifier == (Object)null) && modifier.m_settings != null && modifier.m_settings.m_raise)
			{
				UnlimitedTerrainCompIds.Add(((Object)__instance).GetInstanceID());
				modifier.m_settings.m_raiseDelta = PendingRaiseAmount;
			}
		}

		private static void Postfix()
		{
		}
	}

	[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
	private static class ApplyHeightLimitPatch
	{
		private static void Prefix(TerrainComp __instance)
		{
			if (UnlimitedTerrainCompIds.Contains(((Object)__instance).GetInstanceID()))
			{
				UnlimitedTerrainComp = __instance;
			}
		}

		private static void Postfix(TerrainComp __instance)
		{
			if ((Object)(object)UnlimitedTerrainComp == (Object)(object)__instance)
			{
				UnlimitedTerrainComp = null;
				UnlimitedTerrainCompIds.Remove(((Object)__instance).GetInstanceID());
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.Method(typeof(Mathf), "Clamp", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(float)
			}, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(Plugin), "ClampAppliedHeight", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					instruction.operand = replacement;
				}
				yield return instruction;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "PlacePiece")]
	private static class PlaceTerrainPiecePatch
	{
		private sealed class TerrainOperationState
		{
			internal float RaiseDelta;

			internal float RaiseRadius;

			internal float LevelRadius;

			internal float SmoothRadius;

			internal float PaintRadius;

			internal bool IsRaise;

			internal bool IsLevel;
		}

		private static void Prefix(Player __instance, Piece piece, ref TerrainOperationState __state)
		{
			__state = null;
			HasPendingRaise = false;
			PendingRaiseAmount = 0f;
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !IsHoe(((Humanoid)__instance).RightItem) || !Object.op_Implicit((Object)(object)piece))
			{
				return;
			}
			TerrainOp val = FindTerrainOperation(piece);
			if (!Object.op_Implicit((Object)(object)val) || val.m_settings == null)
			{
				return;
			}
			if (IsLevelOperation(piece, val) && Object.op_Implicit((Object)(object)Instance))
			{
				__state = new TerrainOperationState
				{
					LevelRadius = val.m_settings.m_levelRadius,
					SmoothRadius = val.m_settings.m_smoothRadius,
					PaintRadius = val.m_settings.m_paintRadius,
					IsLevel = true
				};
				val.m_settings.m_levelRadius = Instance._selectedRadius;
				val.m_settings.m_smoothRadius = Instance._selectedRadius;
				val.m_settings.m_paintRadius = Instance._selectedRadius;
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)Localize($"Terrain leveled: area {Instance._selectedRadius:0.##} m", $"Terreno planado: área {Instance._selectedRadius:0.##} m"));
			}
			else if (val.m_settings.m_raise)
			{
				HasPendingRaise = true;
				PendingRaiseAmount = (Object.op_Implicit((Object)(object)Instance) ? Mathf.Max(0.05f, Instance._selectedRaise) : 0f);
				__state = new TerrainOperationState
				{
					RaiseDelta = val.m_settings.m_raiseDelta,
					RaiseRadius = val.m_settings.m_raiseRadius,
					IsRaise = true
				};
				val.m_settings.m_raiseDelta = PendingRaiseAmount;
				val.m_settings.m_raiseRadius = (Object.op_Implicit((Object)(object)Instance) ? Instance._selectedRadius : val.m_settings.m_raiseRadius);
				if (Object.op_Implicit((Object)(object)Instance))
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)Localize($"Terrain raised: area {Instance._selectedRadius:0.##} m, height {PendingRaiseAmount:0.##} m", $"Terreno elevado: área {Instance._selectedRadius:0.##} m, altura {PendingRaiseAmount:0.##} m"));
				}
			}
		}

		private static void Postfix(Piece piece, TerrainOperationState __state)
		{
			if (__state != null && Object.op_Implicit((Object)(object)piece))
			{
				TerrainOp val = FindTerrainOperation(piece);
				if (Object.op_Implicit((Object)(object)val) && val.m_settings != null)
				{
					if (__state.IsRaise)
					{
						val.m_settings.m_raiseDelta = __state.RaiseDelta;
						val.m_settings.m_raiseRadius = __state.RaiseRadius;
					}
					if (__state.IsLevel)
					{
						val.m_settings.m_levelRadius = __state.LevelRadius;
						val.m_settings.m_smoothRadius = __state.SmoothRadius;
						val.m_settings.m_paintRadius = __state.PaintRadius;
					}
				}
			}
			HasPendingRaise = false;
			PendingRaiseAmount = 0f;
		}
	}

	[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
	private static class CameraScrollPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(Plugin), "GetCameraScrollWheel", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					instruction.operand = replacement;
				}
				yield return instruction;
			}
		}
	}

	private enum AdjustmentMode
	{
		Area,
		Height
	}

	private const string PluginGuid = "com.vnts.valadvancedhoe";

	private const string PluginName = "valAdvancedHoe";

	private const string PluginVersion = "0.2.0";

	internal static Plugin Instance;

	internal static float PendingRaiseAmount;

	internal static bool HasPendingRaise;

	internal static TerrainComp UnlimitedTerrainComp;

	internal static readonly HashSet<int> UnlimitedTerrainCompIds = new HashSet<int>();

	private Harmony _harmony;

	private ConfigEntry<string> _language;

	private ConfigEntry<float> _raiseStep;

	private ConfigEntry<float> _minRaise;

	private ConfigEntry<float> _maxRaise;

	private ConfigEntry<float> _previewRadius;

	private ConfigEntry<float> _minRadius;

	private ConfigEntry<float> _radiusStep;

	private ConfigEntry<float> _maxRadius;

	private ConfigEntry<float> _hoeReach;

	private ConfigEntry<KeyCode> _areaKey;

	private ConfigEntry<KeyCode> _heightKey;

	private ConfigEntry<bool> _suppressCameraZoom;

	private ConfigEntry<bool> _enablePreview;

	private ConfigEntry<float> _raycastDistance;

	private ConfigEntry<float> _levelPreviewHeight;

	private ConfigEntry<string> _validPreviewColor;

	private ConfigEntry<string> _invalidPreviewColor;

	private ConfigEntry<float> _validPreviewAlpha;

	private ConfigEntry<float> _invalidPreviewAlpha;

	private ConfigEntry<bool> _showHud;

	private ConfigEntry<bool> _allowUnlimitedRaise;

	private ConfigEntry<string> _planarPieceNames;

	private Color _validColor;

	private Color _invalidColor;

	private float _selectedRaise;

	private float _selectedRadius;

	private AdjustmentMode _adjustmentMode = AdjustmentMode.Height;

	private Player _rangePlayer;

	private float _originalPlaceDistance = -1f;

	private GameObject _preview;

	private Material _previewMaterial;

	private bool _previewValid;

	private bool _previewCanApply;

	private bool _levelMode;

	private string _lastHeldItemName;

	private string _lastDebugState;

	private string _lastTerrainModeDetails;

	private float RaiseMinimum => Mathf.Max(0.01f, _minRaise.Value);

	private float RaiseMaximum => Mathf.Max(RaiseMinimum, _maxRaise.Value);

	private float RadiusMinimum => Mathf.Max(0.1f, _minRadius.Value);

	private float RadiusMaximum => Mathf.Max(RadiusMinimum, _maxRadius.Value);

	private bool IsPortuguese
	{
		get
		{
			if (!string.Equals(_language.Value, "pt-BR", StringComparison.OrdinalIgnoreCase) && !string.Equals(_language.Value, "ptbr", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(_language.Value, "pt_br", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}
	}

	private void Awake()
	{
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c6: Expected O, but got Unknown
		Instance = this;
		_language = ((BaseUnityPlugin)this).Config.Bind<string>("Localization", "Language", "en-US", "In-game language. Supported values: en-US, pt-BR.");
		_raiseStep = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "ScrollStep", 0.5f, "Height added per mouse-wheel step, in meters.");
		_minRaise = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "MinRaise", 0.05f, "Minimum height selectable for one hoe use, in meters.");
		_maxRaise = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "MaxRaise", 8f, "Maximum height added by one hoe use, in meters.");
		_previewRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "PreviewRadius", 4f, "Initial terrain radius, in meters.");
		_minRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "MinRadius", 0.5f, "Minimum selectable terrain radius, in meters.");
		_radiusStep = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "RadiusScrollStep", 1f, "Radius added per mouse-wheel step while Area mode is selected.");
		_maxRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "MaxRadius", 20f, "Maximum terrain radius, in meters.");
		_hoeReach = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain Raise", "HoeReach", 20f, "Maximum placement distance while the hoe is equipped, in meters.");
		_areaKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "AreaKey", (KeyCode)113, "Selects area adjustment mode while the hoe is equipped.");
		_heightKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "HeightKey", (KeyCode)101, "Selects height adjustment mode while the hoe is equipped.");
		_suppressCameraZoom = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "SuppressCameraZoom", true, "Prevents the mouse wheel from zooming the camera while adjusting the hoe.");
		_enablePreview = ((BaseUnityPlugin)this).Config.Bind<bool>("Preview", "Enabled", true, "Shows the custom terrain cylinder preview.");
		_raycastDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Preview", "RaycastDistance", 50f, "Maximum distance used to find terrain for the preview, in meters.");
		_levelPreviewHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Preview", "PlanarHeight", 0.1f, "Visual height of the cylinder while using the planar mode, in meters.");
		_validPreviewColor = ((BaseUnityPlugin)this).Config.Bind<string>("Preview", "ValidColor", "#808080", "Cylinder color when the terrain operation can be applied, as #RRGGBB or #RRGGBBAA.");
		_invalidPreviewColor = ((BaseUnityPlugin)this).Config.Bind<string>("Preview", "InvalidColor", "#CC3333", "Cylinder color when the position is invalid, as #RRGGBB or #RRGGBBAA.");
		_validPreviewAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Preview", "ValidAlpha", 0.28f, "Cylinder opacity when the terrain operation can be applied, from 0 to 1.");
		_invalidPreviewAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Preview", "InvalidAlpha", 0.22f, "Cylinder opacity when the position is invalid, from 0 to 1.");
		_showHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Preview", "ShowHud", true, "Shows the current area, height and adjustment mode on screen.");
		_allowUnlimitedRaise = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain Raise", "AllowBeyondGameLimit", true, "Allows repeated raise operations to go beyond Valheim's normal 8 m limit.");
		_planarPieceNames = ((BaseUnityPlugin)this).Config.Bind<string>("Planar", "PieceNameTokens", "mud_road,level,paved_road", "Comma-separated prefab-name fragments treated as planar operations.");
		_validColor = ParseColor(_validPreviewColor.Value, new Color(0.5f, 0.5f, 0.5f));
		_invalidColor = ParseColor(_invalidPreviewColor.Value, new Color(0.8f, 0.2f, 0.2f));
		_selectedRaise = Mathf.Clamp(_raiseStep.Value, RaiseMinimum, RaiseMaximum);
		_selectedRadius = Mathf.Clamp(_previewRadius.Value, RadiusMinimum, RadiusMaximum);
		_harmony = new Harmony("com.vnts.valadvancedhoe");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)Localize("valAdvancedHoe loaded successfully.", "valAdvancedHoe carregado com sucesso."));
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		ItemData val = (Object.op_Implicit((Object)(object)localPlayer) ? ((Humanoid)localPlayer).RightItem : null);
		string text = val?.m_shared?.m_name ?? "<none>";
		if (text != _lastHeldItemName)
		{
			_lastHeldItemName = text;
			((BaseUnityPlugin)this).Logger.LogInfo((object)Localize("Equipped item detected: " + text, "Item equipado detectado: " + text));
		}
		if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !IsHoe(val))
		{
			RestorePlaceDistance();
			SetDebugState(Localize("hoe not detected", "enxada não detectada"));
			_previewValid = false;
			SetPreviewVisible(visible: false);
		}
		else
		{
			ExtendHoeReach(localPlayer);
			UpdateTerrainMode(localPlayer);
			UpdateAdjustmentInput();
			UpdatePreview(localPlayer, val);
		}
	}

	private void UpdateTerrainMode(Player player)
	{
		Piece selectedPiece = player.GetSelectedPiece();
		TerrainOp val = FindTerrainOperation(selectedPiece);
		_levelMode = IsLevelOperation(selectedPiece, val);
		string text = (Object.op_Implicit((Object)(object)selectedPiece) ? ((Object)selectedPiece).name : "<nenhuma peça>");
		if (Object.op_Implicit((Object)(object)val) && val.m_settings != null)
		{
			text += $" level={val.m_settings.m_level} raise={val.m_settings.m_raise}";
		}
		if (text != _lastTerrainModeDetails)
		{
			_lastTerrainModeDetails = text;
			((BaseUnityPlugin)this).Logger.LogInfo((object)Localize($"Hoe mode: {text} -> planar={_levelMode}", $"Modo da enxada: {text} -> planar={_levelMode}"));
		}
	}

	private void UpdateAdjustmentInput()
	{
		//IL_0017: 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)
		if (_levelMode)
		{
			_adjustmentMode = AdjustmentMode.Area;
		}
		else if (ZInput.GetKeyDown(_areaKey.Value, true))
		{
			_adjustmentMode = AdjustmentMode.Area;
		}
		else if (ZInput.GetKeyDown(_heightKey.Value, true))
		{
			_adjustmentMode = AdjustmentMode.Height;
		}
		float mouseScrollWheel = ZInput.GetMouseScrollWheel();
		if (!(Mathf.Abs(mouseScrollWheel) < 0.01f))
		{
			if (_adjustmentMode == AdjustmentMode.Area)
			{
				float num = Mathf.Max(0.1f, _radiusStep.Value);
				_selectedRadius = Mathf.Clamp(_selectedRadius + Mathf.Sign(mouseScrollWheel) * num, RadiusMinimum, RadiusMaximum);
			}
			else if (!_levelMode)
			{
				float num2 = Mathf.Max(0.05f, _raiseStep.Value);
				_selectedRaise = Mathf.Clamp(_selectedRaise + Mathf.Sign(mouseScrollWheel) * num2, RaiseMinimum, RaiseMaximum);
			}
		}
	}

	private static TerrainOp FindTerrainOperation(Piece piece)
	{
		if (!Object.op_Implicit((Object)(object)piece))
		{
			return null;
		}
		return FindTerrainOperation(((Component)piece).gameObject);
	}

	private static TerrainOp FindTerrainOperation(GameObject root)
	{
		if (!Object.op_Implicit((Object)(object)root))
		{
			return null;
		}
		TerrainOp[] componentsInChildren = root.GetComponentsInChildren<TerrainOp>(true);
		TerrainOp val = null;
		TerrainOp[] array = componentsInChildren;
		foreach (TerrainOp val2 in array)
		{
			if (Object.op_Implicit((Object)(object)val2) && val2.m_settings != null)
			{
				if (val2.m_settings.m_level)
				{
					return val2;
				}
				val = val ?? val2;
			}
		}
		return val;
	}

	private static bool IsLevelOperation(Piece piece, TerrainOp operation)
	{
		if (Object.op_Implicit((Object)(object)operation) && operation.m_settings != null && operation.m_settings.m_level)
		{
			return true;
		}
		string text = (Object.op_Implicit((Object)(object)piece) ? ((Object)piece).name : string.Empty);
		string[] array = (Object.op_Implicit((Object)(object)Instance) ? Instance._planarPieceNames.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) : null);
		if (array == null)
		{
			return false;
		}
		string[] array2 = array;
		foreach (string text2 in array2)
		{
			if (!string.IsNullOrWhiteSpace(text2) && text.IndexOf(text2.Trim(), StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private static Color ParseColor(string value, Color fallback)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		Color result = default(Color);
		if (string.IsNullOrWhiteSpace(value) || !ColorUtility.TryParseHtmlString(value.Trim(), ref result))
		{
			return fallback;
		}
		return result;
	}

	internal static string Localize(string english, string portuguese)
	{
		if (!Object.op_Implicit((Object)(object)Instance) || !Instance.IsPortuguese)
		{
			return english;
		}
		return portuguese;
	}

	private void ExtendHoeReach(Player player)
	{
		if ((Object)(object)_rangePlayer != (Object)(object)player)
		{
			RestorePlaceDistance();
			_rangePlayer = player;
			_originalPlaceDistance = player.m_maxPlaceDistance;
		}
		player.m_maxPlaceDistance = Mathf.Max(_originalPlaceDistance, _hoeReach.Value);
	}

	private void RestorePlaceDistance()
	{
		if (Object.op_Implicit((Object)(object)_rangePlayer) && _originalPlaceDistance >= 0f)
		{
			_rangePlayer.m_maxPlaceDistance = _originalPlaceDistance;
		}
		_rangePlayer = null;
		_originalPlaceDistance = -1f;
	}

	private void UpdatePreview(Player player, ItemData heldItem)
	{
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		_previewValid = false;
		if (!_enablePreview.Value)
		{
			SetPreviewVisible(visible: false);
			return;
		}
		Camera val = Camera.main;
		if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)GameCamera.instance))
		{
			val = ((Component)GameCamera.instance).GetComponentInChildren<Camera>();
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			SetDebugState(Localize("camera not found", "câmera não encontrada"));
			SetPreviewVisible(visible: false);
			return;
		}
		if (((Character)player).InAttack() || !TryGetTerrainHit(val, _raycastDistance.Value, out var hit, out var terrainHeight))
		{
			SetDebugState(Localize("terrain not found by raycast", "terreno não encontrado no raycast"));
			SetPreviewVisible(visible: false);
			return;
		}
		float selectedRadius = _selectedRadius;
		float num = (_levelMode ? Mathf.Max(0.01f, _levelPreviewHeight.Value) : Mathf.Max(0.01f, _selectedRaise));
		EnsurePreview();
		if (!Object.op_Implicit((Object)(object)_preview))
		{
			SetDebugState(Localize("preview could not be created", "não foi possível criar a prévia"));
			return;
		}
		_preview.transform.position = new Vector3(((RaycastHit)(ref hit)).point.x, terrainHeight + num * 0.5f, ((RaycastHit)(ref hit)).point.z);
		_preview.transform.localScale = new Vector3(selectedRadius * 2f, num * 0.5f, selectedRadius * 2f);
		_previewCanApply = Vector3.Distance(((Component)player).transform.position, ((RaycastHit)(ref hit)).point) <= player.m_maxPlaceDistance + 0.1f;
		if (Object.op_Implicit((Object)(object)_previewMaterial) && _previewMaterial.HasProperty("_Color"))
		{
			Color color = (_previewCanApply ? _validColor : _invalidColor);
			color.a = Mathf.Clamp01(_previewCanApply ? _validPreviewAlpha.Value : _invalidPreviewAlpha.Value);
			_previewMaterial.color = color;
		}
		_previewValid = true;
		SetDebugState(Localize("preview active", "preview ativo"));
		SetPreviewVisible(visible: true);
	}

	private void SetDebugState(string state)
	{
		if (!(state == _lastDebugState))
		{
			_lastDebugState = state;
			((BaseUnityPlugin)this).Logger.LogInfo((object)Localize("Preview state: " + state, "Estado da prévia: " + state));
		}
	}

	private static bool TryGetTerrainHit(Camera camera, float maxDistance, out RaycastHit hit, out float terrainHeight)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		hit = default(RaycastHit);
		terrainHeight = 0f;
		RaycastHit[] array = Physics.RaycastAll(camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)), Mathf.Max(1f, maxDistance), -5, (QueryTriggerInteraction)1);
		float num = float.MaxValue;
		bool result = false;
		RaycastHit[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			RaycastHit val = array2[i];
			if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider))
			{
				Heightmap val2 = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Heightmap>();
				if (!Object.op_Implicit((Object)(object)val2))
				{
					val2 = Heightmap.FindHeightmap(((RaycastHit)(ref val)).point);
				}
				if (Object.op_Implicit((Object)(object)val2) && ((RaycastHit)(ref val)).distance < num && Heightmap.GetHeight(((RaycastHit)(ref val)).point, ref terrainHeight))
				{
					hit = val;
					num = ((RaycastHit)(ref val)).distance;
					result = true;
				}
			}
		}
		return result;
	}

	private void EnsurePreview()
	{
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)_preview))
		{
			return;
		}
		_preview = GameObject.CreatePrimitive((PrimitiveType)2);
		((Object)_preview).name = "valAdvancedHoe_RaisePreview";
		Collider component = _preview.GetComponent<Collider>();
		if (Object.op_Implicit((Object)(object)component))
		{
			Object.Destroy((Object)(object)component);
		}
		Renderer component2 = _preview.GetComponent<Renderer>();
		if (!Object.op_Implicit((Object)(object)component2))
		{
			Object.Destroy((Object)(object)_preview);
			_preview = null;
			return;
		}
		Material material = component2.material;
		Shader val = Shader.Find("UI/Default") ?? Shader.Find("Legacy Shaders/Transparent/Diffuse") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Hidden/Internal-Colored");
		_previewMaterial = (Material)((!Object.op_Implicit((Object)(object)val)) ? ((object)material) : ((object)new Material(val)));
		component2.material = _previewMaterial;
		if ((Object)(object)_previewMaterial != (Object)(object)material)
		{
			Object.Destroy((Object)(object)material);
		}
		if (!Object.op_Implicit((Object)(object)_previewMaterial) || ((Object)_previewMaterial.shader).name == "Hidden/InternalErrorShader")
		{
			((BaseUnityPlugin)this).Logger.LogError((object)Localize("Could not obtain a valid shader for the hoe preview.", "Não foi possível obter um shader válido para a prévia da enxada."));
			Object.Destroy((Object)(object)_preview);
			_preview = null;
			return;
		}
		if (_previewMaterial.HasProperty("_MainTex"))
		{
			_previewMaterial.mainTexture = (Texture)(object)Texture2D.whiteTexture;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)Localize(string.Format("Preview shader: {0}; color={1}", ((Object)_previewMaterial.shader).name, _previewMaterial.HasProperty("_Color")), string.Format("Shader da prévia: {0}; cor={1}", ((Object)_previewMaterial.shader).name, _previewMaterial.HasProperty("_Color"))));
		if (_previewMaterial.HasProperty("_Mode"))
		{
			_previewMaterial.SetFloat("_Mode", 3f);
		}
		if (_previewMaterial.HasProperty("_SrcBlend"))
		{
			_previewMaterial.SetInt("_SrcBlend", 5);
		}
		if (_previewMaterial.HasProperty("_DstBlend"))
		{
			_previewMaterial.SetInt("_DstBlend", 10);
		}
		if (_previewMaterial.HasProperty("_ZWrite"))
		{
			_previewMaterial.SetInt("_ZWrite", 0);
		}
		_previewMaterial.renderQueue = 3000;
		component2.shadowCastingMode = (ShadowCastingMode)0;
		component2.receiveShadows = false;
		_preview.SetActive(false);
	}

	private void SetPreviewVisible(bool visible)
	{
		if (Object.op_Implicit((Object)(object)_preview) && _preview.activeSelf != visible)
		{
			_preview.SetActive(visible);
		}
	}

	private void OnGUI()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		if (_previewValid && _showHud.Value)
		{
			GUI.color = Color.white;
			GUI.Label(new Rect((float)Screen.width * 0.5f + 18f, (float)Screen.height * 0.5f + 18f, 300f, 24f), _levelMode ? Localize($"Area: {_selectedRadius:0.##} m   |   Planar: standard height", $"Área: {_selectedRadius:0.##} m   |   Planar: altura padrão") : Localize($"Area: {_selectedRadius:0.##} m   |   Height: {_selectedRaise:0.##} m", $"Área: {_selectedRadius:0.##} m   |   Altura: {_selectedRaise:0.##} m"));
			GUI.Label(new Rect((float)Screen.width * 0.5f + 18f, (float)Screen.height * 0.5f + 38f, 260f, 24f), Localize("Adjusting: " + (_levelMode ? "Planar — area only" : ((_adjustmentMode == AdjustmentMode.Area) ? "Area" : "Height")), "Ajustando: " + (_levelMode ? "Planar — somente Área" : ((_adjustmentMode == AdjustmentMode.Area) ? "Área" : "Altura"))));
		}
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
		}
		RestorePlaceDistance();
		if (Object.op_Implicit((Object)(object)_preview))
		{
			Object.Destroy((Object)(object)_preview);
		}
		if (Object.op_Implicit((Object)(object)_previewMaterial))
		{
			Object.Destroy((Object)(object)_previewMaterial);
		}
	}

	internal static bool IsHoe(ItemData item)
	{
		string text = item?.m_shared?.m_name;
		if (!string.IsNullOrEmpty(text))
		{
			return text.IndexOf("hoe", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	internal static float GetCameraScrollWheel()
	{
		Player localPlayer = Player.m_localPlayer;
		if (!Object.op_Implicit((Object)(object)localPlayer) || !IsHoe(((Humanoid)localPlayer).RightItem) || !Object.op_Implicit((Object)(object)Instance) || !Instance._suppressCameraZoom.Value)
		{
			return ZInput.GetMouseScrollWheel();
		}
		return 0f;
	}

	internal static float ClampRaiseDelta(float value, float min, float max)
	{
		if (!HasPendingRaise)
		{
			return Mathf.Clamp(value, min, max);
		}
		return value;
	}

	internal static float ClampAppliedHeight(float value, float min, float max)
	{
		if (!((Object)(object)UnlimitedTerrainComp != (Object)null) || !Object.op_Implicit((Object)(object)Instance) || !Instance._allowUnlimitedRaise.Value)
		{
			return Mathf.Clamp(value, min, max);
		}
		return value;
	}
}