Decompiled source of HardheimMultiPlant v1.0.0

plugins/MultiPlant.dll

Decompiled 3 hours 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 BepInEx.Logging;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("MultiPlant")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MultiPlant")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("58fda8fc-703c-4199-b3f4-ddcd0647aaa4")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HardheimMultiPlant;

[BepInPlugin("h4nz0.hardheimmultiplant", "Hardheim Multi Plant", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
public class HardheimMultiPlantPlugin : BaseUnityPlugin
{
	public const string ModGuid = "h4nz0.hardheimmultiplant";

	public const string ModName = "Hardheim Multi Plant";

	public const string ModVersion = "1.0.0";

	internal static HardheimMultiPlantPlugin Instance;

	internal static ManualLogSource Log;

	private Harmony _harmony;

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<int> RequiredFarmingSkill;

	internal static ConfigEntry<int> ExtraPlantsAtThreshold;

	internal static ConfigEntry<int> MaxExtraPlants;

	internal static ConfigEntry<float> PlantSpacing;

	internal static ConfigEntry<bool> RequireCultivatorEquipped;

	internal static ConfigEntry<string> AllowedPrefabKeywords;

	internal static ConfigEntry<bool> EnableSnapping;

	internal static ConfigEntry<float> SnapStep;

	internal static ConfigEntry<bool> SnapUseGhostRight;

	internal static ConfigEntry<bool> PreviewExtraPlants;

	internal static ConfigEntry<bool> OnlyLocalPreview;

	internal static ConfigEntry<bool> ExtraPlacementRequiresFreeSpace;

	internal static ConfigEntry<bool> GroundSnapToTerrain;

	internal static ConfigEntry<float> GroundSnapRayHeight;

	internal static ConfigEntry<bool> DebugEnabled;

	internal static ConfigEntry<bool> DebugGhostUpdate;

	internal static ConfigEntry<bool> DebugPlacement;

	internal static ConfigEntry<bool> DebugConfigSync;

	internal static ConfigEntry<bool> DebugShowPositionDetails;

	internal static ConfigEntry<bool> DebugDumpConfigOnLoad;

	internal static ConfigEntry<bool> DebugDumpConfigOnSync;

	internal static ConfigEntry<bool> DebugDumpAdminState;

	internal static ConfigEntry<bool> DebugCollisionCheck;

	internal static ConfigEntry<bool> UseSquarePattern;

	internal static ConfigEntry<bool> UseGroundRaySnap;

	internal static ConfigEntry<float> GroundRayStartHeight;

	internal static ConfigEntry<float> GroundRayDistance;

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

	private static readonly List<Vector3> CachedExtraPositions = new List<Vector3>();

	private static readonly FieldInfo PlacementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

	private static readonly BindingFlags AllInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static string _lastGhostName = string.Empty;

	private static int _lastExtraCount = -1;

	private static bool _lastPreviewVisible = false;

	private static Quaternion _stickyRotation = Quaternion.identity;

	private static bool _hasStickyRotation = false;

	private static Quaternion _lastGoodPreviewRotation = Quaternion.identity;

	private static bool _hasLastGoodPreviewRotation = false;

	private static GameObject _lastPlacedPrefabVisualSource;

	private static string _lastPlacedPrefabName = string.Empty;

	private void Awake()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		CreateConfigValues();
		HookJotunnEvents();
		_harmony = new Harmony("h4nz0.hardheimmultiplant");
		_harmony.PatchAll();
		Log.LogInfo((object)"==================================================");
		Log.LogInfo((object)"Hardheim Multi Plant 1.0.0 betöltve.");
		Log.LogInfo((object)"Jotunn dependency aktív: igen");
		Log.LogInfo((object)"Config sync mód: AdminOnlyStrictness.IfOnServer");
		Log.LogInfo((object)"==================================================");
		if (DebugDumpConfigOnLoad.Value)
		{
			DumpAllConfig("Awake");
		}
	}

	private void OnDestroy()
	{
		try
		{
			_harmony.UnpatchSelf();
		}
		catch
		{
		}
		DestroyPreviewGhosts();
	}

	private void CreateConfigValues()
	{
		Enabled = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Általános", "Enabled", true, "A mod fő kapcsolója. Ha kikapcsolod, sem preview, sem extra ültetés nem fut.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config = ((BaseUnityPlugin)this).Config;
		AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100);
		RequiredFarmingSkill = ConfigFileExtensions.BindConfig<int>(config, "Egyensúly", "RequiredFarmingSkill", 60, "Minimum Farming skill szint, ami felett aktiválódik a többes ültetés.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config2 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 16);
		ExtraPlantsAtThreshold = ConfigFileExtensions.BindConfig<int>(config2, "Egyensúly", "ExtraPlantsAtThreshold", 8, "Ennyi extra növény jelenik meg és ültethető le, amikor a játékos eléri a minimum skill szintet.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config3 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 32);
		MaxExtraPlants = ConfigFileExtensions.BindConfig<int>(config3, "Egyensúly", "MaxExtraPlants", 8, "Maximum ennyi extra növényt enged a mod összesen.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config4 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f);
		PlantSpacing = ConfigFileExtensions.BindConfig<float>(config4, "Elhelyezés", "PlantSpacing", 1.15f, "Az extra növények távolsága az eredeti ültetési ponttól.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		RequireCultivatorEquipped = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Szabályok", "RequireCultivatorEquipped", true, "Ha igaz, a mod csak akkor működik, ha a játékosnál Cultivator van használatban.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		AllowedPrefabKeywords = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Szűrő", "AllowedPrefabKeywords", "carrot,turnip,onion,seed,seedling,sapling,beech,birch,fir,pine,jotunpuffs,magecap,barley,flax", "Vesszővel elválasztott kulcsszavak. Csak az ezekre illeszkedő ültethető ghostokra aktiválódik a mod.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		EnableSnapping = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Snapping", "EnableSnapping", true, "Ha igaz, az extra növények pozíciója rácsra lesz igazítva.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config5 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f);
		SnapStep = ConfigFileExtensions.BindConfig<float>(config5, "Snapping", "SnapStep", 0.5f, "A snapping rácslépése méterben. Például 0.5 = félméteres igazítás.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		SnapUseGhostRight = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Snapping", "SnapUseGhostRight", true, "Ha igaz, az extra növények az aktuális placement ghost jobb oldali tengelye mentén sorakoznak fel. Ha hamis, a játékos jobb oldali tengelyét használja.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		PreviewExtraPlants = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Preview", "PreviewExtraPlants", true, "Ha igaz, ültetés előtt megjelennek az extra ghostok.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		OnlyLocalPreview = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Preview", "OnlyLocalPreview", true, "Ha igaz, a preview csak a helyi játékosnak jelenik meg.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ExtraPlacementRequiresFreeSpace = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Szabályok", "ExtraPlacementRequiresFreeSpace", true, "Ha igaz, az extra növény csak akkor kerül lerakásra, ha a célpozíció szabadnak látszik.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		GroundSnapToTerrain = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Snapping", "GroundSnapToTerrain", true, "Ha igaz, az extra preview és lerakás a talaj felszínére igazodik, nem csak X/Z rácsra.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config6 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f);
		GroundSnapRayHeight = ConfigFileExtensions.BindConfig<float>(config6, "Snapping", "GroundSnapRayHeight", 10f, "Milyen magasról induljon a talajra igazító raycast az extra pozícióknál.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		UseSquarePattern = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Elhelyezés", "UseSquarePattern", true, "Ha igaz, az extra ültetési pontok négyzetes mintában helyezkednek el az eredeti pont körül.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		UseGroundRaySnap = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Snapping", "UseGroundRaySnap", true, "Ha igaz, a számolt extra pontokat lefelé sugárvetéssel a talajhoz igazítja.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config7 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f);
		GroundRayStartHeight = ConfigFileExtensions.BindConfig<float>(config7, "Snapping", "GroundRayStartHeight", 3f, "Ennyivel a célpont fölül indul a lefelé sugárvetés a talaj megkereséséhez.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		ConfigFile config8 = ((BaseUnityPlugin)this).Config;
		val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f);
		GroundRayDistance = ConfigFileExtensions.BindConfig<float>(config8, "Snapping", "GroundRayDistance", 10f, "A lefelé sugárvetés maximális hossza a talaj megkereséséhez.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugEnabled = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugEnabled", false, "Fő debug kapcsoló. Erősen részletes naplózást engedélyez.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugGhostUpdate = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugGhostUpdate", true, "Részletes log az előnézeti ghost frissítésről.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugPlacement = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugPlacement", true, "Részletes log a tényleges extra lerakásról.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugConfigSync = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugConfigSync", true, "Részletes log a Jotunn config sync eseményekről.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugShowPositionDetails = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugShowPositionDetails", true, "Kiírja a számolt pozíciókat, snap előtti és snap utáni adatokat.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugDumpConfigOnLoad = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugDumpConfigOnLoad", true, "A mod indulásakor kiírja az összes fontos konfig értéket.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugDumpConfigOnSync = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugDumpConfigOnSync", true, "Config sync után kiírja az összes fontos konfig értéket.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugDumpAdminState = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugDumpAdminState", true, "Kiírja a Jotunn által ismert admin állapotot és annak változásait.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		DebugCollisionCheck = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Debug", "DebugCollisionCheck", true, "Kiírja a helyfoglalás-ellenőrzés találatait az extra lerakásoknál.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
	}

	private void HookJotunnEvents()
	{
		SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized;
		SynchronizationManager.OnAdminStatusChanged += OnAdminStatusChanged;
	}

	private void OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs args)
	{
		if (DebugEnabled.Value && DebugConfigSync.Value)
		{
			Log.LogInfo((object)"[CFGSYNC] ==================================================");
			Log.LogInfo((object)"[CFGSYNC] Konfig szinkron esemény érkezett.");
			Log.LogInfo((object)("[CFGSYNC] InitialSynchronization = " + args.InitialSynchronization));
			Log.LogInfo((object)("[CFGSYNC] PlayerIsAdmin = " + SafeGetAdminState()));
			Log.LogInfo((object)"[CFGSYNC] ==================================================");
			if (DebugDumpConfigOnSync.Value)
			{
				DumpAllConfig("OnConfigurationSynchronized");
			}
		}
	}

	private void OnAdminStatusChanged()
	{
		if (DebugEnabled.Value && DebugDumpAdminState.Value)
		{
			Log.LogInfo((object)"[ADMIN] ================================================");
			Log.LogInfo((object)"[ADMIN] Admin státusz változás érkezett.");
			Log.LogInfo((object)("[ADMIN] PlayerIsAdmin = " + SafeGetAdminState()));
			Log.LogInfo((object)"[ADMIN] ================================================");
		}
	}

	internal static bool SafeGetAdminState()
	{
		try
		{
			return SynchronizationManager.Instance != null && SynchronizationManager.Instance.PlayerIsAdmin;
		}
		catch
		{
			return false;
		}
	}

	internal static void DumpAllConfig(string source)
	{
		Log.LogInfo((object)("[DUMP][" + source + "] ------------------------------"));
		Log.LogInfo((object)("[DUMP][" + source + "] Enabled = " + Enabled.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] RequiredFarmingSkill = " + RequiredFarmingSkill.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] ExtraPlantsAtThreshold = " + ExtraPlantsAtThreshold.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] MaxExtraPlants = " + MaxExtraPlants.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] PlantSpacing = " + PlantSpacing.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] RequireCultivatorEquipped = " + RequireCultivatorEquipped.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] AllowedPrefabKeywords = " + AllowedPrefabKeywords.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] EnableSnapping = " + EnableSnapping.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] SnapStep = " + SnapStep.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] SnapUseGhostRight = " + SnapUseGhostRight.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] PreviewExtraPlants = " + PreviewExtraPlants.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] OnlyLocalPreview = " + OnlyLocalPreview.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] ExtraPlacementRequiresFreeSpace = " + ExtraPlacementRequiresFreeSpace.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] GroundSnapToTerrain = " + GroundSnapToTerrain.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] GroundSnapRayHeight = " + GroundSnapRayHeight.Value));
		Log.LogInfo((object)("[DUMP][" + source + "] PlayerIsAdmin = " + SafeGetAdminState()));
		Log.LogInfo((object)("[DUMP][" + source + "] ------------------------------"));
	}

	internal static void LogDebug(string msg)
	{
		if (DebugEnabled.Value)
		{
			Log.LogInfo((object)("[DEBUG] " + msg));
		}
	}

	internal static void LogGhost(string msg)
	{
		if (DebugEnabled.Value && DebugGhostUpdate.Value)
		{
			Log.LogInfo((object)("[GHOST] " + msg));
		}
	}

	internal static void LogPlacement(string msg)
	{
		if (DebugEnabled.Value && DebugPlacement.Value)
		{
			Log.LogInfo((object)("[PLACE] " + msg));
		}
	}

	internal static string CleanName(string name)
	{
		return string.IsNullOrEmpty(name) ? string.Empty : name.Replace("(Clone)", "").Trim();
	}

	internal static string[] SplitKeywords(string raw)
	{
		if (string.IsNullOrWhiteSpace(raw))
		{
			return new string[0];
		}
		string[] array = raw.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		List<string> list = new List<string>();
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (!string.IsNullOrWhiteSpace(text))
			{
				list.Add(text);
			}
		}
		return list.ToArray();
	}

	internal static string Vec(Vector3 v)
	{
		return "(" + v.x.ToString("0.000") + ", " + v.y.ToString("0.000") + ", " + v.z.ToString("0.000") + ")";
	}

	internal static GameObject GetPlacementGhost(Player player)
	{
		if ((Object)(object)player == (Object)null || PlacementGhostField == null)
		{
			return null;
		}
		try
		{
			object? value = PlacementGhostField.GetValue(player);
			return (GameObject)((value is GameObject) ? value : null);
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("[GHOST] Nem sikerült kiolvasni az m_placementGhost mezőt: " + ex));
			return null;
		}
	}

	internal static ItemData GetRightItemSafe(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		try
		{
			FieldInfo fieldInfo = typeof(Humanoid).GetField("m_rightItem", AllInstance) ?? typeof(Player).GetField("m_rightItem", AllInstance);
			if (fieldInfo != null)
			{
				object? value = fieldInfo.GetValue(player);
				ItemData val = (ItemData)((value is ItemData) ? value : null);
				if (val != null)
				{
					return val;
				}
			}
		}
		catch
		{
		}
		try
		{
			MethodInfo methodInfo = typeof(Humanoid).GetMethod("GetCurrentWeapon", AllInstance) ?? typeof(Player).GetMethod("GetCurrentWeapon", AllInstance);
			if (methodInfo != null)
			{
				object? obj2 = methodInfo.Invoke(player, null);
				ItemData val2 = (ItemData)((obj2 is ItemData) ? obj2 : null);
				if (val2 != null)
				{
					return val2;
				}
			}
		}
		catch
		{
		}
		return null;
	}

	internal static bool HasCultivatorEquipped(Player player, GameObject placementGhost)
	{
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (!RequireCultivatorEquipped.Value)
		{
			return true;
		}
		ItemData rightItemSafe = GetRightItemSafe(player);
		string text = ((rightItemSafe != null && rightItemSafe.m_shared != null) ? (rightItemSafe.m_shared.m_name ?? string.Empty) : string.Empty);
		string text2 = ((rightItemSafe != null && (Object)(object)rightItemSafe.m_dropPrefab != (Object)null) ? (((Object)rightItemSafe.m_dropPrefab).name ?? string.Empty) : string.Empty);
		string text3 = (((Object)(object)placementGhost != (Object)null) ? CleanName(((Object)placementGhost).name) : string.Empty);
		bool flag = text.IndexOf("cultivator", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("kultiv", StringComparison.OrdinalIgnoreCase) >= 0 || text.Equals("$item_cultivator", StringComparison.OrdinalIgnoreCase) || text2.IndexOf("cultivator", StringComparison.OrdinalIgnoreCase) >= 0;
		bool flag2 = text3.IndexOf("cultivate", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("sapling", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("seed", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("carrot", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("turnip", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("onion", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("barley", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("flax", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("beech", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("birch", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("fir", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("pine", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("jotunpuffs", StringComparison.OrdinalIgnoreCase) >= 0 || text3.IndexOf("magecap", StringComparison.OrdinalIgnoreCase) >= 0;
		bool result = flag || flag2;
		if (DebugEnabled.Value && DebugGhostUpdate.Value)
		{
			Log.LogInfo((object)("[GHOST] HasCultivatorEquipped -> " + result + " | sharedName=" + text + " | dropName=" + text2 + " | ghostName=" + text3));
		}
		return result;
	}

	internal static bool IsPlantPlacement(GameObject placementGhost)
	{
		if ((Object)(object)placementGhost == (Object)null)
		{
			return false;
		}
		string text = CleanName(((Object)placementGhost).name).ToLowerInvariant();
		if (text.Contains("cultivate") || text.Contains("sapling") || text.Contains("seed") || text.Contains("carrot") || text.Contains("turnip") || text.Contains("onion") || text.Contains("barley") || text.Contains("flax") || text.Contains("beech") || text.Contains("birch") || text.Contains("fir") || text.Contains("pine") || text.Contains("jotunpuffs") || text.Contains("magecap"))
		{
			return true;
		}
		return (Object)(object)placementGhost.GetComponent<Piece>() != (Object)null;
	}

	internal static bool IsPlantableGhost(GameObject ghost)
	{
		if ((Object)(object)ghost == (Object)null)
		{
			return false;
		}
		string text = CleanName(((Object)ghost).name);
		if (string.IsNullOrWhiteSpace(text))
		{
			return false;
		}
		string[] array = SplitKeywords(AllowedPrefabKeywords.Value);
		for (int i = 0; i < array.Length; i++)
		{
			if (text.IndexOf(array[i], StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	internal static bool TryGetFarmingSkillType(out SkillType skillType)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected I4, but got Unknown
		skillType = (SkillType)0;
		try
		{
			skillType = (SkillType)(int)(SkillType)Enum.Parse(typeof(SkillType), "Farming");
			return true;
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("[SKILL] Nem sikerült feloldani a Skills.SkillType.Farming enumot: " + ex));
			return false;
		}
	}

	internal static float GetFarmingLevel(Player player)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return 0f;
		}
		if (!TryGetFarmingSkillType(out var skillType))
		{
			return 0f;
		}
		try
		{
			return ((Character)player).GetSkillLevel(skillType);
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("[SKILL] Nem sikerült lekérni a Farming skill szintet: " + ex));
			return 0f;
		}
	}

	internal static int GetExtraPlantCount(Player player)
	{
		float farmingLevel = GetFarmingLevel(player);
		int num = Mathf.Max(0, RequiredFarmingSkill.Value);
		if (farmingLevel < (float)num)
		{
			if (DebugEnabled.Value && DebugGhostUpdate.Value)
			{
				Log.LogInfo((object)("[COUNT] Farming skill túl alacsony. current=" + farmingLevel + " required=" + num));
			}
			return 0;
		}
		int num2 = Mathf.Max(0, ExtraPlantsAtThreshold.Value);
		if (farmingLevel > (float)num)
		{
			int num3 = Mathf.FloorToInt((farmingLevel - (float)num) / 20f);
			num2 += num3;
		}
		num2 = Mathf.Clamp(num2, 0, Mathf.Max(0, MaxExtraPlants.Value));
		if (DebugEnabled.Value && (DebugGhostUpdate.Value || DebugPlacement.Value))
		{
			Log.LogInfo((object)("[COUNT] Farming=" + farmingLevel + " required=" + num + " -> extra=" + num2));
		}
		return num2;
	}

	internal static float SnapValue(float value, float step)
	{
		return Mathf.Round(value / step) * step;
	}

	internal static Vector3 ApplySnapping(Vector3 position)
	{
		//IL_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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)
		if (!EnableSnapping.Value)
		{
			return position;
		}
		float step = Mathf.Max(0.05f, SnapStep.Value);
		return new Vector3(SnapValue(position.x, step), position.y, SnapValue(position.z, step));
	}

	internal static bool TrySnapToGround(Vector3 position, out Vector3 snapped)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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)
		snapped = position;
		if (!GroundSnapToTerrain.Value)
		{
			return false;
		}
		float num = Mathf.Max(1f, GroundSnapRayHeight.Value);
		Vector3 val = position + Vector3.up * num;
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(new Ray(val, Vector3.down), ref val2, num * 2f + 20f, -1, (QueryTriggerInteraction)1))
		{
			snapped = new Vector3(position.x, ((RaycastHit)(ref val2)).point.y, position.z);
			if (DebugEnabled.Value && DebugShowPositionDetails.Value)
			{
				Log.LogInfo((object)("[GROUND] hit=" + (((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) ? ((Object)((Component)((RaycastHit)(ref val2)).collider).gameObject).name : "null") + " | from=" + Vec(position) + " -> " + Vec(snapped)));
			}
			return true;
		}
		if (DebugEnabled.Value && DebugShowPositionDetails.Value)
		{
			Log.LogInfo((object)("[GROUND] Nincs talaj találat: " + Vec(position)));
		}
		return false;
	}

	internal static Vector3 SnapToGround(Vector3 position)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: 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_0039: 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_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: 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)
		if (!UseGroundRaySnap.Value)
		{
			return position;
		}
		Vector3 val = position + Vector3.up * Mathf.Max(0.5f, GroundRayStartHeight.Value);
		float num = Mathf.Max(1f, GroundRayDistance.Value);
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, Vector3.down, ref val2, num, -1, (QueryTriggerInteraction)1))
		{
			if (DebugEnabled.Value && DebugShowPositionDetails.Value)
			{
				Log.LogInfo((object)("[GROUND] hit point=" + Vec(((RaycastHit)(ref val2)).point) + " collider=" + (Object.op_Implicit((Object)(object)((RaycastHit)(ref val2)).collider) ? ((Object)((RaycastHit)(ref val2)).collider).name : "null")));
			}
			return new Vector3(position.x, ((RaycastHit)(ref val2)).point.y, position.z);
		}
		if (DebugEnabled.Value && DebugShowPositionDetails.Value)
		{
			Log.LogInfo((object)("[GROUND] nincs találat. start=" + Vec(val) + " dist=" + num));
		}
		return position;
	}

	internal static List<int> BuildOffsetPattern(int count)
	{
		List<int> list = new List<int>();
		int num = 1;
		while (list.Count < count)
		{
			list.Add(num);
			if (list.Count >= count)
			{
				break;
			}
			list.Add(-num);
			num++;
		}
		return list;
	}

	internal static bool CanPlaceAt(Vector3 position)
	{
		//IL_0053: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		if (!ExtraPlacementRequiresFreeSpace.Value)
		{
			if (DebugEnabled.Value && DebugCollisionCheck.Value)
			{
				Log.LogInfo((object)("[COLLISION] Ellenőrzés kikapcsolva. Pozíció automatikusan elfogadva: " + Vec(position)));
			}
			return true;
		}
		Collider[] array = Physics.OverlapSphere(position, 0.18f, -1, (QueryTriggerInteraction)1);
		bool flag = false;
		foreach (Collider val in array)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
			{
				continue;
			}
			string text = ((Object)((Component)val).gameObject).name ?? string.Empty;
			if (text.Length != 0)
			{
				bool flag2 = text.IndexOf("cultivated", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("ghost", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("vfx", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("terrain", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("PlantingPreview", StringComparison.OrdinalIgnoreCase) >= 0;
				if (DebugEnabled.Value && DebugCollisionCheck.Value)
				{
					Log.LogInfo((object)("[COLLISION] Hit: " + text + " | ignore=" + flag2 + " | pos=" + Vec(position)));
				}
				if (!flag2)
				{
					flag = true;
				}
			}
		}
		if (DebugEnabled.Value && DebugCollisionCheck.Value)
		{
			Log.LogInfo((object)("[COLLISION] Eredmény pozíción " + Vec(position) + " -> blocked=" + flag));
		}
		return !flag;
	}

	internal static bool CanPreviewPlaceAt(Vector3 position)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if (!ExtraPlacementRequiresFreeSpace.Value)
		{
			return true;
		}
		Collider[] array = Physics.OverlapSphere(position, 0.18f, -1, (QueryTriggerInteraction)1);
		foreach (Collider val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
			{
				string text = ((Object)((Component)val).gameObject).name ?? string.Empty;
				if (text.Length != 0 && text.IndexOf("cultivated", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("ghost", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("vfx", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("terrain", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("PlantingPreview", StringComparison.OrdinalIgnoreCase) < 0)
				{
					return false;
				}
			}
		}
		return true;
	}

	internal static Quaternion GetPreviewRotation(GameObject sourceGhost)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: 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_0035: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: 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_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_0051: 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_006a: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		if (_hasStickyRotation)
		{
			_lastGoodPreviewRotation = _stickyRotation;
			_hasLastGoodPreviewRotation = true;
			return _stickyRotation;
		}
		if ((Object)(object)sourceGhost != (Object)null)
		{
			Quaternion rotation = sourceGhost.transform.rotation;
			Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
			if (rotation != Quaternion.identity || eulerAngles.y > 0.01f)
			{
				_lastGoodPreviewRotation = rotation;
				_hasLastGoodPreviewRotation = true;
				return rotation;
			}
		}
		if (_hasLastGoodPreviewRotation)
		{
			return _lastGoodPreviewRotation;
		}
		return Quaternion.identity;
	}

	internal static List<Vector3> CalculateExtraPositions(Player player, GameObject sourceGhost)
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: 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)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: 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_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_0375: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0383: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_038a: Unknown result type (might be due to invalid IL or missing references)
		//IL_038c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0391: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0406: Unknown result type (might be due to invalid IL or missing references)
		//IL_0418: Unknown result type (might be due to invalid IL or missing references)
		//IL_043d: Unknown result type (might be due to invalid IL or missing references)
		CachedExtraPositions.Clear();
		if ((Object)(object)player == (Object)null || (Object)(object)sourceGhost == (Object)null)
		{
			LogGhost("CalculateExtraPositions megszakítva: player vagy sourceGhost null.");
			return CachedExtraPositions;
		}
		int extraPlantCount = GetExtraPlantCount(player);
		if (extraPlantCount <= 0)
		{
			LogGhost("CalculateExtraPositions: extraCount <= 0, nincs extra pozíció.");
			return CachedExtraPositions;
		}
		float num = Mathf.Max(0.2f, PlantSpacing.Value);
		Vector3 position = sourceGhost.transform.position;
		Quaternion previewRotation = GetPreviewRotation(sourceGhost);
		Vector3 val = previewRotation * Vector3.right;
		Vector3 val2 = previewRotation * Vector3.forward;
		val.y = 0f;
		val2.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
		{
			val = Vector3.right;
		}
		if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
		{
			val2 = Vector3.forward;
		}
		((Vector3)(ref val)).Normalize();
		((Vector3)(ref val2)).Normalize();
		List<Vector3> list = new List<Vector3>();
		if (UseSquarePattern.Value)
		{
			List<Vector2Int> list2 = new List<Vector2Int>
			{
				new Vector2Int(1, 1),
				new Vector2Int(-1, 1),
				new Vector2Int(1, -1),
				new Vector2Int(-1, -1),
				new Vector2Int(1, 0),
				new Vector2Int(-1, 0),
				new Vector2Int(0, 1),
				new Vector2Int(0, -1),
				new Vector2Int(2, 2),
				new Vector2Int(-2, 2),
				new Vector2Int(2, -2),
				new Vector2Int(-2, -2),
				new Vector2Int(2, 0),
				new Vector2Int(-2, 0),
				new Vector2Int(0, 2),
				new Vector2Int(0, -2)
			};
			for (int i = 0; i < extraPlantCount && i < list2.Count; i++)
			{
				Vector2Int val3 = list2[i];
				list.Add((val * (float)((Vector2Int)(ref val3)).x + val2 * (float)((Vector2Int)(ref val3)).y) * num);
			}
		}
		else
		{
			Vector3 val4;
			if (!SnapUseGhostRight.Value)
			{
				Vector3 right = ((Component)player).transform.right;
				val4 = ((Vector3)(ref right)).normalized;
			}
			else
			{
				val4 = val;
			}
			Vector3 val5 = val4;
			List<int> list3 = BuildOffsetPattern(extraPlantCount);
			for (int j = 0; j < list3.Count; j++)
			{
				list.Add(val5 * ((float)list3[j] * num));
			}
		}
		if (DebugEnabled.Value && DebugShowPositionDetails.Value)
		{
			Log.LogInfo((object)("[POS] origin=" + Vec(position) + " spacing=" + num + " extraCount=" + extraPlantCount + " square=" + UseSquarePattern.Value));
		}
		for (int k = 0; k < list.Count; k++)
		{
			Vector3 val6 = position + list[k];
			Vector3 val7 = ApplySnapping(val6);
			Vector3 position2 = val7;
			bool flag = false;
			if (TrySnapToGround(val7, out var snapped))
			{
				position2 = snapped;
				flag = true;
			}
			Vector3 val8 = SnapToGround(position2);
			CachedExtraPositions.Add(val8);
			if (DebugEnabled.Value && DebugShowPositionDetails.Value)
			{
				Log.LogInfo((object)("[POS] idx=" + k + " raw=" + Vec(val6) + " snappedXZ=" + Vec(val7) + " terrainHit=" + flag + " final=" + Vec(val8)));
			}
		}
		return CachedExtraPositions;
	}

	internal static GameObject GetBestPreviewVisualSource(Player player, GameObject sourceGhost)
	{
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		GameObject placementGhost = GetPlacementGhost(player);
		if ((Object)(object)placementGhost == (Object)null)
		{
			LogGhost("Preview visual source: placementGhost null.");
			return null;
		}
		string text = CleanName(((Object)placementGhost).name);
		if (text.Equals("cultivate_v2", StringComparison.OrdinalIgnoreCase))
		{
			if ((Object)(object)_lastPlacedPrefabVisualSource != (Object)null)
			{
				LogGhost("Preview visual source fallback: utolsó lerakott prefab: " + _lastPlacedPrefabName);
				return _lastPlacedPrefabVisualSource;
			}
			LogGhost("Preview visual source: cultivate_v2 -> nincs még lerakott prefab, skip.");
			return null;
		}
		LogGhost("Preview visual source: placementGhost használva: " + text);
		return placementGhost;
	}

	internal static bool CopyVisualChildrenOnly(GameObject source, GameObject targetRoot)
	{
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)source == (Object)null || (Object)(object)targetRoot == (Object)null)
		{
			return false;
		}
		bool result = false;
		Renderer[] componentsInChildren = source.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
			{
				GameObject gameObject = ((Component)val).gameObject;
				GameObject val2;
				try
				{
					val2 = Object.Instantiate<GameObject>(gameObject);
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("[GHOST] Renderer child klónozás hiba: " + ex));
					continue;
				}
				((Object)val2).name = "PreviewVisual_" + ((Object)gameObject).name;
				val2.transform.SetParent(targetRoot.transform, false);
				Transform transform = gameObject.transform;
				val2.transform.localPosition = source.transform.InverseTransformPoint(transform.position);
				val2.transform.localRotation = Quaternion.Inverse(source.transform.rotation) * transform.rotation;
				val2.transform.localScale = transform.lossyScale;
				StripNonVisualComponents(val2);
				Renderer[] componentsInChildren2 = val2.GetComponentsInChildren<Renderer>(true);
				if (componentsInChildren2.Length != 0)
				{
					result = true;
				}
				else
				{
					Object.Destroy((Object)(object)val2);
				}
			}
		}
		return result;
	}

	internal static void StripNonVisualComponents(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
		Collider[] componentsInChildren2 = go.GetComponentsInChildren<Collider>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			Object.Destroy((Object)(object)componentsInChildren2[j]);
		}
		Rigidbody[] componentsInChildren3 = go.GetComponentsInChildren<Rigidbody>(true);
		for (int k = 0; k < componentsInChildren3.Length; k++)
		{
			Object.Destroy((Object)(object)componentsInChildren3[k]);
		}
		Joint[] componentsInChildren4 = go.GetComponentsInChildren<Joint>(true);
		for (int l = 0; l < componentsInChildren4.Length; l++)
		{
			Object.Destroy((Object)(object)componentsInChildren4[l]);
		}
		ZNetView[] componentsInChildren5 = go.GetComponentsInChildren<ZNetView>(true);
		for (int m = 0; m < componentsInChildren5.Length; m++)
		{
			Object.Destroy((Object)(object)componentsInChildren5[m]);
		}
		ZSyncTransform[] componentsInChildren6 = go.GetComponentsInChildren<ZSyncTransform>(true);
		for (int n = 0; n < componentsInChildren6.Length; n++)
		{
			Object.Destroy((Object)(object)componentsInChildren6[n]);
		}
		Piece[] componentsInChildren7 = go.GetComponentsInChildren<Piece>(true);
		for (int num = 0; num < componentsInChildren7.Length; num++)
		{
			Object.Destroy((Object)(object)componentsInChildren7[num]);
		}
		WearNTear[] componentsInChildren8 = go.GetComponentsInChildren<WearNTear>(true);
		for (int num2 = 0; num2 < componentsInChildren8.Length; num2++)
		{
			Object.Destroy((Object)(object)componentsInChildren8[num2]);
		}
		TerrainModifier[] componentsInChildren9 = go.GetComponentsInChildren<TerrainModifier>(true);
		for (int num3 = 0; num3 < componentsInChildren9.Length; num3++)
		{
			Object.Destroy((Object)(object)componentsInChildren9[num3]);
		}
		Plant[] componentsInChildren10 = go.GetComponentsInChildren<Plant>(true);
		for (int num4 = 0; num4 < componentsInChildren10.Length; num4++)
		{
			Object.Destroy((Object)(object)componentsInChildren10[num4]);
		}
		Pickable[] componentsInChildren11 = go.GetComponentsInChildren<Pickable>(true);
		for (int num5 = 0; num5 < componentsInChildren11.Length; num5++)
		{
			Object.Destroy((Object)(object)componentsInChildren11[num5]);
		}
	}

	internal static void PreparePreviewVisuals(GameObject go)
	{
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//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_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: 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_0119: 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_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: 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_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: 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_01f8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
		Color val4 = default(Color);
		foreach (Renderer val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			val.enabled = true;
			val.shadowCastingMode = (ShadowCastingMode)0;
			val.receiveShadows = false;
			Material[] sharedMaterials = val.sharedMaterials;
			Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
			for (int j = 0; j < sharedMaterials.Length; j++)
			{
				Material val2 = sharedMaterials[j];
				if ((Object)(object)val2 == (Object)null)
				{
					array[j] = null;
					continue;
				}
				Material val3;
				try
				{
					val3 = new Material(val2);
				}
				catch
				{
					array[j] = val2;
					continue;
				}
				try
				{
					((Color)(ref val4))..ctor(0.35f, 1f, 0.35f, 0.65f);
					if (val3.HasProperty("_Color"))
					{
						Color color = val3.color;
						color.r *= val4.r;
						color.g *= val4.g;
						color.b *= val4.b;
						color.a = Mathf.Min(color.a, val4.a);
						val3.color = color;
					}
					if (val3.HasProperty("_BaseColor"))
					{
						Color color2 = val3.GetColor("_BaseColor");
						color2.r *= val4.r;
						color2.g *= val4.g;
						color2.b *= val4.b;
						color2.a = Mathf.Min(color2.a, val4.a);
						val3.SetColor("_BaseColor", color2);
					}
					if (val3.HasProperty("_EmissionColor"))
					{
						val3.EnableKeyword("_EMISSION");
						val3.SetColor("_EmissionColor", new Color(0.08f, 0.35f, 0.08f, 1f));
					}
					if (val3.HasProperty("_ZWrite"))
					{
						val3.SetInt("_ZWrite", 0);
					}
					val3.renderQueue = 3000;
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("[GHOST] Preview material finomítás hiba: " + ex));
				}
				array[j] = val3;
			}
			val.materials = array;
		}
	}

	internal static void SetPreviewValidState(GameObject go, bool valid)
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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_015f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Material[] materials = val.materials;
			foreach (Material val2 in materials)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Color val3 = (valid ? new Color(0.35f, 1f, 0.35f, 0.65f) : new Color(1f, 0.25f, 0.25f, 0.65f));
				try
				{
					if (val2.HasProperty("_Color"))
					{
						Color color = val2.color;
						color.r = val3.r;
						color.g = val3.g;
						color.b = val3.b;
						color.a = val3.a;
						val2.color = color;
					}
					if (val2.HasProperty("_BaseColor"))
					{
						val2.SetColor("_BaseColor", val3);
					}
					if (val2.HasProperty("_EmissionColor"))
					{
						val2.EnableKeyword("_EMISSION");
						val2.SetColor("_EmissionColor", valid ? new Color(0.08f, 0.35f, 0.08f, 1f) : new Color(0.35f, 0.05f, 0.05f, 1f));
					}
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("[GHOST] SetPreviewValidState hiba: " + ex));
				}
			}
		}
	}

	internal static GameObject CreatePreviewGhost(Player player, GameObject sourceGhost)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		GameObject bestPreviewVisualSource = GetBestPreviewVisualSource(player, sourceGhost);
		if ((Object)(object)bestPreviewVisualSource == (Object)null)
		{
			return null;
		}
		GameObject val = new GameObject("PlantingPreview_" + CleanName(((Object)bestPreviewVisualSource).name));
		val.SetActive(false);
		if (!CopyVisualChildrenOnly(bestPreviewVisualSource, val))
		{
			Object.Destroy((Object)(object)val);
			Log.LogWarning((object)"[GHOST] Nem sikerült vizuális elemet másolni a preview ghosthoz.");
			return null;
		}
		PreparePreviewVisuals(val);
		int num = val.GetComponentsInChildren<Renderer>(true).Length;
		LogGhost("Vizuális preview ghost létrehozva: " + ((Object)val).name + " | source=" + CleanName(((Object)bestPreviewVisualSource).name) + " | renderers=" + num);
		return val;
	}

	internal static void EnsurePreviewGhostCount(int count, Player player, GameObject sourceGhost)
	{
		while (PreviewGhosts.Count < count)
		{
			GameObject val = CreatePreviewGhost(player, sourceGhost);
			if ((Object)(object)val == (Object)null)
			{
				break;
			}
			PreviewGhosts.Add(val);
		}
		while (PreviewGhosts.Count > count)
		{
			int index = PreviewGhosts.Count - 1;
			if ((Object)(object)PreviewGhosts[index] != (Object)null)
			{
				Object.Destroy((Object)(object)PreviewGhosts[index]);
			}
			PreviewGhosts.RemoveAt(index);
		}
	}

	internal static void DestroyPreviewGhosts()
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < PreviewGhosts.Count; i++)
		{
			if ((Object)(object)PreviewGhosts[i] != (Object)null)
			{
				Object.Destroy((Object)(object)PreviewGhosts[i]);
			}
		}
		PreviewGhosts.Clear();
		CachedExtraPositions.Clear();
		_hasStickyRotation = false;
		_stickyRotation = Quaternion.identity;
		_lastGoodPreviewRotation = Quaternion.identity;
		_hasLastGoodPreviewRotation = false;
		LogGhost("Minden preview ghost törölve.");
	}

	internal static void HidePreviewGhosts()
	{
		for (int i = 0; i < PreviewGhosts.Count; i++)
		{
			if ((Object)(object)PreviewGhosts[i] != (Object)null)
			{
				PreviewGhosts[i].SetActive(false);
			}
		}
		if (_lastPreviewVisible)
		{
			LogGhost("Preview ghostok elrejtve.");
		}
		_lastPreviewVisible = false;
		_hasStickyRotation = false;
	}

	internal static void UpdatePreviewGhosts(Player player)
	{
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		if (!Enabled.Value || !PreviewExtraPlants.Value)
		{
			HidePreviewGhosts();
			return;
		}
		if ((Object)(object)player == (Object)null)
		{
			HidePreviewGhosts();
			return;
		}
		if (OnlyLocalPreview.Value && (Object)(object)player != (Object)(object)Player.m_localPlayer)
		{
			HidePreviewGhosts();
			return;
		}
		GameObject placementGhost = GetPlacementGhost(player);
		if ((Object)(object)placementGhost == (Object)null)
		{
			HidePreviewGhosts();
			return;
		}
		string text = CleanName(((Object)placementGhost).name);
		int extraPlantCount = GetExtraPlantCount(player);
		bool flag = HasCultivatorEquipped(player, placementGhost);
		bool flag2 = IsPlantPlacement(placementGhost);
		bool flag3 = IsPlantableGhost(placementGhost) || flag2;
		bool flag4 = flag3 && flag && extraPlantCount > 0;
		if (DebugEnabled.Value && DebugGhostUpdate.Value && (text != _lastGhostName || extraPlantCount != _lastExtraCount || flag4 != _lastPreviewVisible))
		{
			Log.LogInfo((object)("[GHOST] Állapotváltás | ghost=" + text + " | cultivator=" + flag + " | plantPlacement=" + flag2 + " | plantable=" + flag3 + " | extraCount=" + extraPlantCount + " | shouldShow=" + flag4));
			_lastGhostName = text;
			_lastExtraCount = extraPlantCount;
		}
		if (!flag4)
		{
			HidePreviewGhosts();
			return;
		}
		List<Vector3> list = CalculateExtraPositions(player, placementGhost);
		EnsurePreviewGhostCount(list.Count, player, placementGhost);
		Quaternion previewRotation = GetPreviewRotation(placementGhost);
		if (_hasStickyRotation)
		{
			try
			{
				placementGhost.transform.rotation = previewRotation;
			}
			catch
			{
			}
		}
		for (int i = 0; i < PreviewGhosts.Count; i++)
		{
			GameObject val = PreviewGhosts[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			if (i >= list.Count)
			{
				val.SetActive(false);
				continue;
			}
			bool valid = CanPreviewPlaceAt(list[i]);
			Vector3 val2 = list[i] + Vector3.up * 0.08f;
			val.transform.SetPositionAndRotation(val2, previewRotation);
			SetPreviewValidState(val, valid);
			if (!val.activeSelf)
			{
				val.SetActive(true);
			}
			if (!DebugEnabled.Value || !DebugGhostUpdate.Value || !DebugShowPositionDetails.Value)
			{
				continue;
			}
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			int num = 0;
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if ((Object)(object)componentsInChildren[j] != (Object)null && componentsInChildren[j].enabled)
				{
					num++;
				}
			}
			Log.LogInfo((object)("[GHOST] Preview[" + i + "] -> " + Vec(list[i]) + " | valid=" + valid + " | renderers=" + componentsInChildren.Length + " | enabled=" + num + " | activeSelf=" + val.activeSelf));
		}
		_lastPreviewVisible = true;
	}

	internal static void PlaceExtraPlants(Player player, Piece piece, Quaternion rot)
	{
		//IL_035b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: 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_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null)
		{
			LogPlacement("PlaceExtraPlants megszakítva: player vagy piece null.");
			return;
		}
		if (!Enabled.Value)
		{
			LogPlacement("PlaceExtraPlants megszakítva: mod kikapcsolva.");
			return;
		}
		GameObject placementGhost = GetPlacementGhost(player);
		if ((Object)(object)placementGhost == (Object)null)
		{
			LogPlacement("PlaceExtraPlants megszakítva: nincs aktív placement ghost.");
			return;
		}
		if (!HasCultivatorEquipped(player, placementGhost))
		{
			LogPlacement("PlaceExtraPlants megszakítva: nincs Cultivator.");
			return;
		}
		if (!IsPlantableGhost(placementGhost) && !IsPlantPlacement(placementGhost))
		{
			LogPlacement("PlaceExtraPlants megszakítva: a placement ghost nem támogatott növény.");
			return;
		}
		if (CachedExtraPositions.Count <= 0)
		{
			LogPlacement("PlaceExtraPlants megszakítva: nincs cache-elt extra pozíció.");
			return;
		}
		GameObject gameObject = ((Component)piece).gameObject;
		if ((Object)(object)gameObject == (Object)null)
		{
			LogPlacement("PlaceExtraPlants megszakítva: piece.gameObject null.");
			return;
		}
		_lastPlacedPrefabVisualSource = gameObject;
		_lastPlacedPrefabName = CleanName(((Object)gameObject).name);
		_stickyRotation = rot;
		_hasStickyRotation = true;
		_lastGoodPreviewRotation = rot;
		_hasLastGoodPreviewRotation = true;
		LogPlacement("Extra lerakás indul. piece=" + CleanName(((Object)gameObject).name) + " cachedPositions=" + CachedExtraPositions.Count + " | rotY=" + ((Quaternion)(ref rot)).eulerAngles.y.ToString("0.0"));
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < CachedExtraPositions.Count; i++)
		{
			Vector3 val = CachedExtraPositions[i];
			if (!CanPlaceAt(val))
			{
				num2++;
				LogPlacement("Pozíció tiltva: index=" + i + " pos=" + Vec(val));
				continue;
			}
			try
			{
				GameObject val2 = Object.Instantiate<GameObject>(gameObject, val, rot);
				((Object)val2).name = CleanName(((Object)gameObject).name);
				Piece component = val2.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null)
				{
					try
					{
						component.SetCreator(player.GetPlayerID());
					}
					catch (Exception ex)
					{
						Log.LogWarning((object)("[PLACE] SetCreator hiba: " + ex));
					}
				}
				ZNetView component2 = val2.GetComponent<ZNetView>();
				if ((Object)(object)component2 != (Object)null && component2.IsValid())
				{
					try
					{
						ZDO zDO = component2.GetZDO();
						if (zDO != null)
						{
							zDO.SetOwner(ZDOMan.GetSessionID());
						}
					}
					catch (Exception ex2)
					{
						Log.LogWarning((object)("[PLACE] ZDO owner beállítás hiba: " + ex2));
					}
				}
				num++;
				LogPlacement("Extra növény lerakva: index=" + i + " pos=" + Vec(val) + " name=" + ((Object)val2).name);
			}
			catch (Exception ex3)
			{
				Log.LogWarning((object)("[PLACE] Extra növény lerakás hiba index=" + i + " pos=" + Vec(val) + " -> " + ex3));
			}
		}
		LogPlacement("Extra lerakás vége. placed=" + num + " blocked=" + num2 + " requested=" + CachedExtraPositions.Count);
	}
}
[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
public static class Player_UpdatePlacementGhost_Patch
{
	[HarmonyPostfix]
	private static void Postfix(Player __instance)
	{
		try
		{
			if ((Object)(object)__instance != (Object)null)
			{
				HardheimMultiPlantPlugin.UpdatePreviewGhosts(__instance);
			}
		}
		catch (Exception ex)
		{
			HardheimMultiPlantPlugin.Log.LogWarning((object)("[PATCH] UpdatePlacementGhost postfix hiba: " + ex));
		}
	}
}
[HarmonyPatch(typeof(Player), "PlacePiece")]
public static class Player_PlacePiece_Patch
{
	[HarmonyPostfix]
	private static void Postfix(Player __instance, Piece piece, Vector3 pos, Quaternion rot, bool doAttack)
	{
		//IL_0007: 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)
		try
		{
			HardheimMultiPlantPlugin.LogPlacement("Player.PlacePiece postfix meghívva. pos=" + HardheimMultiPlantPlugin.Vec(pos) + " doAttack=" + doAttack);
			HardheimMultiPlantPlugin.PlaceExtraPlants(__instance, piece, rot);
		}
		catch (Exception ex)
		{
			HardheimMultiPlantPlugin.Log.LogWarning((object)("[PATCH] PlacePiece postfix hiba: " + ex));
		}
	}
}
[HarmonyPatch(typeof(Player), "UpdatePlacement")]
public static class Player_UpdatePlacement_Patch
{
	[HarmonyPostfix]
	private static void Postfix(Player __instance, bool takeInput)
	{
		try
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				GameObject placementGhost = HardheimMultiPlantPlugin.GetPlacementGhost(__instance);
				if ((Object)(object)placementGhost == (Object)null)
				{
					HardheimMultiPlantPlugin.HidePreviewGhosts();
				}
			}
		}
		catch (Exception ex)
		{
			HardheimMultiPlantPlugin.Log.LogWarning((object)("[PATCH] UpdatePlacement postfix hiba: " + ex));
		}
	}
}
[HarmonyPatch(typeof(Game), "Logout")]
public static class Game_Logout_Patch
{
	[HarmonyPrefix]
	private static void Prefix()
	{
		try
		{
			HardheimMultiPlantPlugin.DestroyPreviewGhosts();
		}
		catch (Exception ex)
		{
			HardheimMultiPlantPlugin.Log.LogWarning((object)("[PATCH] Logout prefix hiba: " + ex));
		}
	}
}