Decompiled source of ValheimMassFarm v1.0.0

plugins/ValheimMassFarm.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ValheimMassFarm")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ValheimMassFarm")]
[assembly: AssemblyTitle("ValheimMassFarm")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ValheimMassFarm;

[BepInPlugin("SuperVikingDepartment.ValheimMassFarm", "ValheimMassFarm", "1.0.0")]
public class MassFarmPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "SuperVikingDepartment.ValheimMassFarm";

	public const string PluginName = "ValheimMassFarm";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	internal static ConfigEntry<string> ToggleKeyName;

	internal static ConfigEntry<string> SnapKeyName;

	internal static ConfigEntry<float> SpacingMultiplier;

	internal static ConfigEntry<bool> DebugLogging;

	internal static KeyCode ToggleKey = (KeyCode)118;

	internal static KeyCode SnapKey = (KeyCode)44;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Expected O, but got Unknown
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		ToggleKeyName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ToggleKey", "V", "开关「3x3 密植」模式的按键。需手持耕耘机并选中作物(树苗/种子)时才生效。填 KeyCode 名称,如 V / B / LeftAlt / Mouse3。");
		SnapKeyName = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SnapKey", "Comma", "开关「自动吸附」的按键(默认逗号)。开启后,下一块 3x3 会自动贴合上一块,按最大密度无缝拼接。填 KeyCode 名称,如 Comma / Period / N。");
		SpacingMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpacingMultiplier", 1f, "种植间距系数。间距 = 2 × 作物生长半径 × 该系数。默认 1.0 即游戏允许的最大密度;若个别作物出现「空间不足」,可略微调大(如 1.05)。");
		DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DebugLogging", false, "输出补丁细节日志,用于排查问题。正常游玩建议关闭。");
		ToggleKey = ParseKey(ToggleKeyName.Value, (KeyCode)118);
		SnapKey = ParseKey(SnapKeyName.Value, (KeyCode)44);
		_harmony = new Harmony("SuperVikingDepartment.ValheimMassFarm");
		try
		{
			_harmony.PatchAll(typeof(Patches));
		}
		catch (Exception ex)
		{
			Log.LogError((object)("[MassFarm] PatchAll 失败:" + ex));
		}
		LogPatchStatus();
		Log.LogInfo((object)"ValheimMassFarm loaded (v1.0.0)");
		Log.LogInfo((object)$"[MassFarm] 热键:密植={ToggleKey},吸附={SnapKey};间距系数={SpacingMultiplier.Value}");
	}

	private static KeyCode ParseKey(string raw, KeyCode fallback)
	{
		//IL_001a: 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)
		if (!string.IsNullOrEmpty(raw) && Enum.TryParse<KeyCode>(raw.Trim(), ignoreCase: true, out KeyCode result))
		{
			return result;
		}
		return fallback;
	}

	private static void LogPatchStatus()
	{
		CheckPatch(typeof(Player), "UpdatePlacementGhost");
		CheckPatch(typeof(Player), "TryPlacePiece");
	}

	private static void CheckPatch(Type type, string method)
	{
		MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			Log.LogError((object)("[MassFarm][diag] " + type.Name + "." + method + " 未找到!游戏版本可能不兼容。"));
		}
		else
		{
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
			int valueOrDefault = (patchInfo?.Postfixes?.Count).GetValueOrDefault();
			int valueOrDefault2 = (patchInfo?.Prefixes?.Count).GetValueOrDefault();
			Log.LogInfo((object)$"[MassFarm][diag] {type.Name}.{method}: prefix={valueOrDefault2}, postfix={valueOrDefault}");
		}
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		GridPreview.Dispose();
	}

	private void Update()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			GridPreview.Hide();
		}
		else
		{
			if (((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || Console.IsVisible())
			{
				return;
			}
			if (ZInput.GetKeyDown(ToggleKey, false))
			{
				FarmState.MassMode = !FarmState.MassMode;
				if (!FarmState.MassMode)
				{
					FarmState.Reset();
				}
				Message(FarmState.MassMode ? "3x3 密植:开" : "3x3 密植:关");
				Log.LogInfo((object)("[MassFarm] 3x3 密植 = " + FarmState.MassMode));
			}
			if (ZInput.GetKeyDown(SnapKey, false))
			{
				FarmState.AutoSnap = !FarmState.AutoSnap;
				Message(FarmState.AutoSnap ? "自动吸附:开(下一块贴合上一块)" : "自动吸附:关");
				Log.LogInfo((object)("[MassFarm] 自动吸附 = " + FarmState.AutoSnap));
			}
		}
	}

	internal static void Message(string msg)
	{
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, msg, 0, (Sprite)null, false);
			}
		}
		catch
		{
		}
	}
}
internal static class FarmState
{
	public static bool MassMode;

	public static bool AutoSnap;

	public static bool HasAnchor;

	public static Vector3 AnchorCenter;

	public static Vector3 AnchorForward = Vector3.forward;

	public static Vector3 AnchorRight = Vector3.right;

	public static Quaternion AnchorRot = Quaternion.identity;

	public static readonly List<Vector3> PlacedBlocks = new List<Vector3>();

	public static int LastStepRight = 1;

	public static int LastStepForward = 0;

	public static bool HasBlock;

	public static Vector3 BlockCenter;

	public static Vector3 BlockForward = Vector3.forward;

	public static Vector3 BlockRight = Vector3.right;

	public static Quaternion BlockRot = Quaternion.identity;

	public static float BlockSpacing = 1f;

	public static bool BlockSetsAnchor = true;

	public static void Reset()
	{
		HasAnchor = false;
		HasBlock = false;
		PlacedBlocks.Clear();
		LastStepRight = 1;
		LastStepForward = 0;
	}
}
[HarmonyPatch]
internal static class Patches
{
	private static readonly FieldInfo FPlacementGhost = AccessTools.Field(typeof(Player), "m_placementGhost");

	private static readonly FieldInfo FBuildPieces = AccessTools.Field(typeof(Player), "m_buildPieces");

	private static readonly MethodInfo MGetBuildStamina = AccessTools.Method(typeof(Player), "GetBuildStamina", (Type[])null, (Type[])null);

	private static readonly MethodInfo MGetPlaceDurability = AccessTools.Method(typeof(Player), "GetPlaceDurability", (Type[])null, (Type[])null);

	private static GameObject GetGhost(Player p)
	{
		if (!(FPlacementGhost != null))
		{
			return null;
		}
		object? value = FPlacementGhost.GetValue(p);
		return (GameObject)((value is GameObject) ? value : null);
	}

	private static Plant FindPlant(Piece piece)
	{
		if ((Object)(object)piece == (Object)null)
		{
			return null;
		}
		Plant component = ((Component)piece).GetComponent<Plant>();
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		component = ((Component)piece).GetComponentInChildren<Plant>(true);
		if ((Object)(object)component != (Object)null)
		{
			return component;
		}
		return ((Component)piece).GetComponentInParent<Plant>();
	}

	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	[HarmonyPostfix]
	private static void UpdatePlacementGhost_Post(Player __instance)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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_012b: 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_0138: 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_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: 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_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		if (!FarmState.MassMode)
		{
			FarmState.HasBlock = false;
			GridPreview.Hide();
			return;
		}
		GameObject ghost = GetGhost(__instance);
		Piece val = (((Object)(object)ghost != (Object)null) ? ghost.GetComponentInParent<Piece>() : null);
		Plant val2 = FindPlant(val);
		if ((Object)(object)ghost == (Object)null || !ghost.activeInHierarchy || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			FarmState.HasBlock = false;
			GridPreview.Hide();
			return;
		}
		if ((int)__instance.GetPlacementStatus() != 0)
		{
			FarmState.HasBlock = false;
			GridPreview.Hide();
			return;
		}
		float num = ((val2.m_growRadius > 0.01f) ? val2.m_growRadius : 0.5f);
		float num2 = Mathf.Max(0.05f, 2f * num * MassFarmPlugin.SpacingMultiplier.Value) + 0.02f;
		Vector3 val3 = ghost.transform.forward;
		Vector3 val4 = ghost.transform.right;
		val3.y = 0f;
		val4.y = 0f;
		if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
		{
			val3 = Vector3.forward;
		}
		else
		{
			((Vector3)(ref val3)).Normalize();
		}
		if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
		{
			val4 = Vector3.right;
		}
		else
		{
			((Vector3)(ref val4)).Normalize();
		}
		Quaternion val5 = Quaternion.LookRotation(val3, Vector3.up);
		Vector3 position = ghost.transform.position;
		Vector3 val6 = position;
		bool blockSetsAnchor = true;
		if (FarmState.AutoSnap && FarmState.HasAnchor)
		{
			bool ok;
			Vector3 val7 = ComputeSnap(position, num2, out ok);
			if (ok && IsCellValid(val, val7))
			{
				val6 = val7;
				val3 = FarmState.AnchorForward;
				val4 = FarmState.AnchorRight;
				val5 = FarmState.AnchorRot;
			}
			else
			{
				blockSetsAnchor = false;
			}
		}
		val6.y = ZoneSystem.instance.GetGroundHeight(val6);
		FarmState.HasBlock = true;
		FarmState.BlockCenter = val6;
		FarmState.BlockForward = val3;
		FarmState.BlockRight = val4;
		FarmState.BlockRot = val5;
		FarmState.BlockSpacing = num2;
		FarmState.BlockSetsAnchor = blockSetsAnchor;
		ghost.transform.position = val6;
		ghost.transform.rotation = val5;
		GridPreview.Show(val6, val4, val3, num2);
	}

	private static Vector3 ComputeSnap(Vector3 aim, float spacing, out bool ok)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: 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)
		Vector3 val = aim - FarmState.AnchorCenter;
		val.y = 0f;
		float num = 3f * spacing;
		float num2 = Vector3.Dot(val, FarmState.AnchorRight);
		float num3 = Vector3.Dot(val, FarmState.AnchorForward);
		int num4;
		int num5;
		if (((Vector3)(ref val)).sqrMagnitude < num * num * 0.0625f)
		{
			num4 = FarmState.LastStepRight;
			num5 = FarmState.LastStepForward;
		}
		else
		{
			num4 = Mathf.RoundToInt(num2 / num);
			num5 = Mathf.RoundToInt(num3 / num);
			if (num4 == 0 && num5 == 0)
			{
				if (Mathf.Abs(num2) >= Mathf.Abs(num3))
				{
					num4 = ((num2 >= 0f) ? 1 : (-1));
				}
				else
				{
					num5 = ((num3 >= 0f) ? 1 : (-1));
				}
			}
		}
		int num6 = ((num4 != 0) ? ((num4 > 0) ? 1 : (-1)) : 0);
		int num7 = ((num5 != 0) ? ((num5 > 0) ? 1 : (-1)) : 0);
		if (num6 == 0 && num7 == 0)
		{
			num6 = 1;
		}
		FarmState.LastStepRight = num6;
		FarmState.LastStepForward = num7;
		Vector3 val2 = Cell(num4, num5, num);
		int num8 = 0;
		while (IsBlockOccupied(val2, spacing) && num8 < 24)
		{
			num4 += num6;
			num5 += num7;
			val2 = Cell(num4, num5, num);
			num8++;
		}
		ok = num8 < 24;
		return val2;
	}

	private static Vector3 Cell(int i, int j, float pitch)
	{
		//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_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		return FarmState.AnchorCenter + FarmState.AnchorRight * ((float)i * pitch) + FarmState.AnchorForward * ((float)j * pitch);
	}

	private static bool IsBlockOccupied(Vector3 cand, float spacing)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		float num = spacing * 0.5f;
		float num2 = num * num;
		for (int i = 0; i < FarmState.PlacedBlocks.Count; i++)
		{
			Vector3 val = cand - FarmState.PlacedBlocks[i];
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < num2)
			{
				return true;
			}
		}
		return false;
	}

	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	[HarmonyPostfix]
	private static void TryPlacePiece_Post(Player __instance, Piece piece, bool __result)
	{
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		Plant val = FindPlant(piece);
		if (MassFarmPlugin.DebugLogging.Value)
		{
			MassFarmPlugin.Log.LogInfo((object)($"[MassFarm] TryPlacePiece_Post: result={__result}, massMode={FarmState.MassMode}, " + string.Format("hasBlock={0}, piece={1}, ", FarmState.HasBlock, ((Object)(object)piece == (Object)null) ? "null" : ((Object)piece).name) + $"plantFound={(Object)(object)val != (Object)null}"));
		}
		if (__result && FarmState.MassMode && FarmState.HasBlock && !((Object)(object)val == (Object)null))
		{
			Vector3 blockCenter = FarmState.BlockCenter;
			int num = PlantNeighbors(__instance, piece);
			if (FarmState.BlockSetsAnchor)
			{
				FarmState.HasAnchor = true;
				FarmState.AnchorCenter = blockCenter;
				FarmState.AnchorForward = FarmState.BlockForward;
				FarmState.AnchorRight = FarmState.BlockRight;
				FarmState.AnchorRot = FarmState.BlockRot;
			}
			FarmState.PlacedBlocks.Add(blockCenter);
			if (MassFarmPlugin.DebugLogging.Value)
			{
				MassFarmPlugin.Log.LogInfo((object)($"[MassFarm] block center={blockCenter} spacing={FarmState.BlockSpacing:0.###} " + $"neighbors={num} anchor={FarmState.HasAnchor}"));
			}
		}
	}

	private static int PlantNeighbors(Player player, Piece piece)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0120: 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)
		//IL_0128: 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_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: 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_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		bool globalKey = ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey());
		Inventory inventory = ((Humanoid)player).GetInventory();
		Vector3 blockCenter = FarmState.BlockCenter;
		Vector3 blockRight = FarmState.BlockRight;
		Vector3 blockForward = FarmState.BlockForward;
		float blockSpacing = FarmState.BlockSpacing;
		Quaternion blockRot = FarmState.BlockRot;
		float num = 0f;
		if (MGetBuildStamina != null)
		{
			try
			{
				num = (float)MGetBuildStamina.Invoke(player, null);
			}
			catch
			{
				num = 0f;
			}
		}
		ItemData rightItem = ((Humanoid)player).RightItem;
		bool flag = rightItem?.m_shared.m_useDurability ?? false;
		float num2 = 0f;
		if (flag && MGetPlaceDurability != null)
		{
			try
			{
				num2 = (float)MGetPlaceDurability.Invoke(player, new object[1] { rightItem });
			}
			catch
			{
				num2 = 0f;
			}
		}
		PieceTable val = (PieceTable)((FBuildPieces != null) ? /*isinst with value type is only supported in some contexts*/: null);
		SkillType val2 = (SkillType)(((Object)(object)val != (Object)null) ? ((int)val.m_skill) : 0);
		int num3 = 0;
		for (int i = -1; i <= 1; i++)
		{
			for (int j = -1; j <= 1; j++)
			{
				if (i == 0 && j == 0)
				{
					continue;
				}
				Vector3 val3 = blockCenter + blockRight * ((float)i * blockSpacing) + blockForward * ((float)j * blockSpacing);
				val3.y = ZoneSystem.instance.GetGroundHeight(val3);
				Vector3 val4 = val3 - ((Component)player).transform.position;
				if (!(((Vector3)(ref val4)).sqrMagnitude > 100f) && IsCellValid(piece, val3))
				{
					if ((!globalKey && !player.HaveRequirements(piece, (RequirementMode)0)) || (num > 0f && !((Character)player).HaveStamina(num)))
					{
						break;
					}
					bool flag2 = ((inventory != null && inventory.ItemCheated(piece.m_resources, -1, true)) || player.NoCostCheat()) && !PlayerProfile.s_bypassCheatChecks;
					try
					{
						player.PlacePiece(piece, val3, blockRot, false, flag2);
					}
					catch (Exception ex)
					{
						MassFarmPlugin.Log.LogError((object)("[MassFarm] PlacePiece failed: " + ex));
						break;
					}
					if (!globalKey)
					{
						player.ConsumeResources(piece.m_resources, 0, -1, 1);
					}
					if (num > 0f)
					{
						((Character)player).UseStamina(num);
					}
					if (flag && rightItem != null)
					{
						rightItem.m_durability -= num2 * Game.m_durabilityRate;
					}
					if ((int)val2 != 0)
					{
						((Character)player).RaiseSkill(val2, 1f);
					}
					Game.instance.IncrementPlayerStat((PlayerStatType)2, 1f, flag2);
					Game.instance.GetPlayerProfile().IncrementStatBuildPiecePlaced(piece.m_name, 1f, flag2);
					num3++;
				}
			}
		}
		return num3;
	}

	private static bool IsCellValid(Piece piece, Vector3 pos)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Invalid comparison between Unknown and I4
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		Heightmap val = Heightmap.FindHeightmap(pos);
		if ((piece.m_groundPiece || piece.m_groundOnly) && (Object)(object)val == (Object)null)
		{
			return false;
		}
		if (piece.m_cultivatedGroundOnly && ((Object)(object)val == (Object)null || !val.IsCultivated(pos)))
		{
			return false;
		}
		if (piece.m_vegetationGroundOnly)
		{
			bool flag = (Object)(object)val == (Object)null;
			if (!flag)
			{
				Biome biome = val.GetBiome(pos, 0.02f, false);
				float vegetationMask = val.GetVegetationMask(pos);
				flag = (((int)biome == 32) ? (vegetationMask > 0.1f) : (vegetationMask < 0.25f));
			}
			if (flag)
			{
				return false;
			}
		}
		if ((int)piece.m_onlyInBiome != 0 && (Heightmap.FindBiome(pos) & piece.m_onlyInBiome) == 0)
		{
			return false;
		}
		if (Location.IsInsideNoBuildLocation(pos))
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(pos, 0f, false, false))
		{
			return false;
		}
		return true;
	}
}
internal static class GridPreview
{
	private const int Cells = 3;

	private static GameObject _root;

	private static readonly List<LineRenderer> _lines = new List<LineRenderer>();

	public static void Show(Vector3 center, Vector3 right, Vector3 forward, float spacing)
	{
		//IL_003d: 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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_00db: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		EnsureInit();
		if (_lines.Count == 0)
		{
			return;
		}
		float num = 1f;
		for (int i = 0; i <= 3; i++)
		{
			float num2 = ((float)i - num) * spacing;
			LineRenderer val = _lines[i];
			for (int j = 0; j <= 3; j++)
			{
				float num3 = ((float)j - num) * spacing;
				Vector3 val2 = center + right * num2 + forward * num3;
				val2.y = ZoneSystem.instance.GetGroundHeight(val2) + 0.06f;
				val.SetPosition(j, val2);
			}
			((Renderer)val).enabled = true;
		}
		for (int k = 0; k <= 3; k++)
		{
			float num4 = ((float)k - num) * spacing;
			LineRenderer val3 = _lines[4 + k];
			for (int l = 0; l <= 3; l++)
			{
				float num5 = ((float)l - num) * spacing;
				Vector3 val4 = center + forward * num4 + right * num5;
				val4.y = ZoneSystem.instance.GetGroundHeight(val4) + 0.06f;
				val3.SetPosition(l, val4);
			}
			((Renderer)val3).enabled = true;
		}
	}

	public static void Hide()
	{
		for (int i = 0; i < _lines.Count; i++)
		{
			if ((Object)(object)_lines[i] != (Object)null)
			{
				((Renderer)_lines[i]).enabled = false;
			}
		}
	}

	public static void Dispose()
	{
		_lines.Clear();
		if ((Object)(object)_root != (Object)null)
		{
			Object.Destroy((Object)(object)_root);
			_root = null;
		}
	}

	private static void EnsureInit()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_0062: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_root != (Object)null)
		{
			return;
		}
		_root = new GameObject("ValheimMassFarm_GridPreview");
		Object.DontDestroyOnLoad((Object)(object)_root);
		Material val = FindLineMaterial();
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(0.35f, 1f, 0.45f, 0.85f);
		int num = 8;
		for (int i = 0; i < num; i++)
		{
			GameObject val3 = new GameObject("grid_line_" + i);
			val3.transform.SetParent(_root.transform, false);
			LineRenderer val4 = val3.AddComponent<LineRenderer>();
			val4.useWorldSpace = true;
			val4.widthMultiplier = 0.02f;
			val4.positionCount = 4;
			val4.numCapVertices = 0;
			if ((Object)(object)val != (Object)null)
			{
				((Renderer)val4).material = val;
			}
			val4.startColor = val2;
			val4.endColor = val2;
			((Renderer)val4).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val4).receiveShadows = false;
			((Renderer)val4).enabled = false;
			_lines.Add(val4);
		}
	}

	private static Material FindLineMaterial()
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		try
		{
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Default-Line")
				{
					return val;
				}
			}
		}
		catch
		{
		}
		Shader val2 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
		if (!((Object)(object)val2 != (Object)null))
		{
			return null;
		}
		return new Material(val2);
	}
}