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("f4ffda28-275e-405d-906b-28e0d2f550e2")]
[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.2.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.2.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> UseSelectedPlantRequiredSpace;
internal static ConfigEntry<float> PlantRequiredSpaceMultiplier;
internal static ConfigEntry<float> MinimumSmallPlantSpacing;
internal static ConfigEntry<float> MinimumTreePlantSpacing;
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;
internal static ConfigEntry<bool> RequireRealGroundHit;
internal static ConfigEntry<float> GroundNormalMinY;
internal static ConfigEntry<bool> CheckExistingPlants;
internal static ConfigEntry<float> ExistingPlantCheckMultiplier;
internal static ConfigEntry<bool> CheckNearbyObjectsForGrowthSpace;
internal static ConfigEntry<float> NearbyObjectCheckMultiplier;
private static readonly List<GameObject> PreviewGhosts = new List<GameObject>();
private static readonly List<Vector3> CachedExtraPositions = new List<Vector3>();
private static readonly List<Vector2Int> CachedExtraCells = new List<Vector2Int>();
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 static string _lastSelectedPlantKey = 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.2.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, 10f);
PlantSpacing = ConfigFileExtensions.BindConfig<float>(config4, "Elhelyezés", "PlantSpacing", 1.15f, "Régi/fallback távolság. Csak akkor használja, ha az aktuálisan ültetett növényből nem tud minimum helyet kiolvasni.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
UseSelectedPlantRequiredSpace = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Elhelyezés", "UseSelectedPlantRequiredSpace", true, "Ha igaz, a rács távolságát az aktuálisan kiválasztott növény Plant komponenséből / collider méretéből számolja, nem egy fix közös értékből.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config5 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f);
PlantRequiredSpaceMultiplier = ConfigFileExtensions.BindConfig<float>(config5, "Elhelyezés", "PlantRequiredSpaceMultiplier", 1.05f, "Szorzó az aktuális növény minimum helyigényére. 1.05 = kis biztonsági ráhagyás.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config6 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f);
MinimumSmallPlantSpacing = ConfigFileExtensions.BindConfig<float>(config6, "Elhelyezés", "MinimumSmallPlantSpacing", 1.15f, "Minimum rácstávolság kis növényeknél, ha a játékból kiolvasott érték ennél kisebb lenne.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config7 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f);
MinimumTreePlantSpacing = ConfigFileExtensions.BindConfig<float>(config7, "Elhelyezés", "MinimumTreePlantSpacing", 4f, "Minimum rácstávolság fáknál/csemetéknél, ha a játékból kiolvasott érték ennél kisebb lenne.", 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", false, "Régi X/Z rács-snapping kapcsoló. Alapból kikapcsolva, mert a 3x3 previewt szétcsúsztathatja vagy eltolhatja a vanilla középső ghosthoz képest.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config8 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f);
SnapStep = ConfigFileExtensions.BindConfig<float>(config8, "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 config9 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f);
GroundSnapRayHeight = ConfigFileExtensions.BindConfig<float>(config9, "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 config10 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f);
GroundRayStartHeight = ConfigFileExtensions.BindConfig<float>(config10, "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 config11 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f);
GroundRayDistance = ConfigFileExtensions.BindConfig<float>(config11, "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);
RequireRealGroundHit = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Snapping", "RequireRealGroundHit", true, "Ha igaz, az extra ghost/növény csak akkor jelenik meg és csak akkor kerül lerakásra, ha a lefelé raycast valódi terepet/Heightmap-et talál. Kerítésre, játékosra, itemre nem snapel.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config12 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f);
GroundNormalMinY = ConfigFileExtensions.BindConfig<float>(config12, "Snapping", "GroundNormalMinY", 0.55f, "Minimum talaj-normál Y érték. 1 = vízszintes, 0.55 körül még lejtős talajt enged, de falat/kerítést nem.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
CheckExistingPlants = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Szabályok", "CheckExistingPlants", true, "Ha igaz, az extra ghost és extra ültetés figyeli a már elültetett növényeket is, és pirosra vált / kihagyja a túl közeli pontokat.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config13 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f);
ExistingPlantCheckMultiplier = ConfigFileExtensions.BindConfig<float>(config13, "Szabályok", "ExistingPlantCheckMultiplier", 0.95f, "A kiválasztott növény spacing értékének ekkora részén belül már túl közelinek számít egy meglévő növény. 0.95 = majdnem teljes spacing.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
CheckNearbyObjectsForGrowthSpace = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Szabályok", "CheckNearbyObjectsForGrowthSpace", true, "Ha igaz, a preview és az extra ültetés nem csak meglévő növényeket figyel, hanem építményeket és tereptárgyakat is a növekedési hely körül. Így nem enged túl közel kerítéshez, falhoz, ládához stb.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
ConfigFile config14 = ((BaseUnityPlugin)this).Config;
val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f);
NearbyObjectCheckMultiplier = ConfigFileExtensions.BindConfig<float>(config14, "Szabályok", "NearbyObjectCheckMultiplier", 0.55f, "A kiválasztott növény spacing értékének ekkora részén belül számít túl közelinek egy építmény vagy tereptárgy. Kis növénynél 0.55 kb. 0.63m, fáknál arányosan nagyobb.", 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 + "] UseSelectedPlantRequiredSpace = " + UseSelectedPlantRequiredSpace.Value));
Log.LogInfo((object)("[DUMP][" + source + "] PlantRequiredSpaceMultiplier = " + PlantRequiredSpaceMultiplier.Value));
Log.LogInfo((object)("[DUMP][" + source + "] MinimumSmallPlantSpacing = " + MinimumSmallPlantSpacing.Value));
Log.LogInfo((object)("[DUMP][" + source + "] MinimumTreePlantSpacing = " + MinimumTreePlantSpacing.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 + "] CheckExistingPlants = " + CheckExistingPlants.Value));
Log.LogInfo((object)("[DUMP][" + source + "] ExistingPlantCheckMultiplier = " + ExistingPlantCheckMultiplier.Value));
Log.LogInfo((object)("[DUMP][" + source + "] CheckNearbyObjectsForGrowthSpace = " + CheckNearbyObjectsForGrowthSpace.Value));
Log.LogInfo((object)("[DUMP][" + source + "] NearbyObjectCheckMultiplier = " + NearbyObjectCheckMultiplier.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);
if (text3.StartsWith("HH_", StringComparison.OrdinalIgnoreCase))
{
return false;
}
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);
if (text.StartsWith("HH_", StringComparison.OrdinalIgnoreCase))
{
return false;
}
string text2 = text.ToLowerInvariant();
return text2.Contains("sapling") || text2.Contains("seed") || text2.Contains("carrot") || text2.Contains("turnip") || text2.Contains("onion") || text2.Contains("barley") || text2.Contains("flax") || text2.Contains("beech") || text2.Contains("birch") || text2.Contains("fir") || text2.Contains("pine") || text2.Contains("jotunpuffs") || text2.Contains("magecap");
}
internal static bool IsPlantableGhost(GameObject ghost)
{
if ((Object)(object)ghost == (Object)null)
{
return false;
}
string text = CleanName(((Object)ghost).name);
if (text.StartsWith("HH_"))
{
return false;
}
string text2 = text;
if (string.IsNullOrWhiteSpace(text2))
{
return false;
}
string[] array = SplitKeywords(AllowedPrefabKeywords.Value);
for (int i = 0; i < array.Length; i++)
{
if (text2.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 Piece GetSelectedPieceSafe(Player player)
{
if ((Object)(object)player == (Object)null)
{
return null;
}
try
{
FieldInfo field = typeof(Player).GetField("m_buildPieces", AllInstance);
PieceTable val = (PieceTable)((field != null) ? /*isinst with value type is only supported in some contexts*/: null);
if ((Object)(object)val == (Object)null)
{
return null;
}
MethodInfo method = typeof(PieceTable).GetMethod("GetSelectedPiece", AllInstance, null, Type.EmptyTypes, null);
if (method != null)
{
object? obj = method.Invoke(val, null);
Piece val2 = (Piece)((obj is Piece) ? obj : null);
if ((Object)(object)val2 != (Object)null)
{
return val2;
}
}
FieldInfo field2 = typeof(PieceTable).GetField("m_selectedPiece", AllInstance);
if (field2 != null)
{
object? value = field2.GetValue(val);
Piece val3 = (Piece)((value is Piece) ? value : null);
if ((Object)(object)val3 != (Object)null)
{
return val3;
}
}
}
catch (Exception ex)
{
if (DebugEnabled.Value && DebugGhostUpdate.Value)
{
Log.LogInfo((object)("[SELECTED] Nem sikerült kiolvasni az aktuális Piece-t: " + ex.Message));
}
}
return null;
}
internal static string GetPlantKey(GameObject placementGhost, Piece selectedPiece)
{
string text = (((Object)(object)selectedPiece != (Object)null && (Object)(object)((Component)selectedPiece).gameObject != (Object)null) ? CleanName(((Object)((Component)selectedPiece).gameObject).name) : string.Empty);
string text2 = (((Object)(object)placementGhost != (Object)null) ? CleanName(((Object)placementGhost).name) : string.Empty);
return text + "|" + text2;
}
internal static bool IsSmallPlantName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}
string text = name.ToLowerInvariant();
return text.Contains("carrot") || text.Contains("turnip") || text.Contains("onion") || text.Contains("barley") || text.Contains("flax") || text.Contains("jotunpuffs") || text.Contains("magecap");
}
internal static bool IsTreePlantName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}
string text = name.ToLowerInvariant();
return text.Contains("beech") || text.Contains("birch") || text.Contains("fir") || text.Contains("pine") || text.Contains("oak") || text.Contains("yggdrasil");
}
internal static float GetExplicitPlantSpacingByName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
return 0f;
}
string name2 = name.ToLowerInvariant();
if (IsSmallPlantName(name2))
{
return Mathf.Max(0.2f, MinimumSmallPlantSpacing.Value);
}
if (IsTreePlantName(name2))
{
return Mathf.Max(1f, MinimumTreePlantSpacing.Value);
}
return 0f;
}
internal static float ReadPlantRequiredSpace(GameObject plantObject)
{
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: 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_0170: 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_0179: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)plantObject == (Object)null)
{
return 0f;
}
float num = 0f;
Plant componentInChildren = plantObject.GetComponentInChildren<Plant>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
FieldInfo[] fields = typeof(Plant).GetFields(AllInstance);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType != typeof(float))
{
continue;
}
string text = fieldInfo.Name.ToLowerInvariant();
if (!text.Contains("radius") && !text.Contains("space") && !text.Contains("distance"))
{
continue;
}
try
{
float num2 = (float)fieldInfo.GetValue(componentInChildren);
if (num2 > num && num2 >= 0.05f && num2 <= 20f)
{
num = num2;
}
}
catch
{
}
}
}
if (num <= 0f)
{
Collider[] componentsInChildren = plantObject.GetComponentsInChildren<Collider>(true);
foreach (Collider val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && !val.isTrigger)
{
Bounds bounds = val.bounds;
Vector3 size = ((Bounds)(ref bounds)).size;
float num3 = Mathf.Max(size.x, size.z);
if (num3 > num && num3 >= 0.05f && num3 <= 20f)
{
num = num3;
}
}
}
}
return num;
}
internal static float GetSpacingForSelectedPlant(Player player, GameObject sourceGhost, Piece selectedPiece)
{
float num = Mathf.Max(0.2f, PlantSpacing.Value);
if (!UseSelectedPlantRequiredSpace.Value)
{
return num;
}
GameObject val = (((Object)(object)selectedPiece != (Object)null) ? ((Component)selectedPiece).gameObject : null);
string text = (((Object)(object)val != (Object)null) ? CleanName(((Object)val).name) : string.Empty);
string text2 = (((Object)(object)sourceGhost != (Object)null) ? CleanName(((Object)sourceGhost).name) : string.Empty);
string name = text + "|" + text2;
float explicitPlantSpacingByName = GetExplicitPlantSpacingByName(name);
if (explicitPlantSpacingByName > 0f)
{
if (DebugEnabled.Value && (DebugGhostUpdate.Value || DebugPlacement.Value))
{
Log.LogInfo((object)("[SPACING] explicit selected=" + text + " | ghost=" + text2 + " | finalSpacing=" + explicitPlantSpacingByName.ToString("0.###")));
}
return Mathf.Clamp(explicitPlantSpacingByName, 0.2f, 10f);
}
float num2 = ReadPlantRequiredSpace(val);
float num3 = Mathf.Max(0.5f, PlantRequiredSpaceMultiplier.Value);
float num4 = ((num2 > 0f) ? (num2 * num3) : num);
num4 = Mathf.Max(num4, num);
num4 = Mathf.Clamp(num4, 0.2f, 10f);
if (DebugEnabled.Value && (DebugGhostUpdate.Value || DebugPlacement.Value))
{
Log.LogInfo((object)("[SPACING] fallback selected=" + text + " | ghost=" + text2 + " | plantRequired=" + num2.ToString("0.###") + " | multiplier=" + num3.ToString("0.###") + " | finalSpacing=" + num4.ToString("0.###")));
}
return num4;
}
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 IsValidPlantingGroundHit(RaycastHit hit)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//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)
if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
{
return false;
}
if (((RaycastHit)(ref hit)).normal.y < Mathf.Clamp(GroundNormalMinY.Value, 0.1f, 1f))
{
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[GROUND] Elutasítva: túl meredek felület. collider=" + ((Object)((RaycastHit)(ref hit)).collider).name + " normalY=" + ((RaycastHit)(ref hit)).normal.y.ToString("0.###")));
}
return false;
}
GameObject gameObject = ((Component)((RaycastHit)(ref hit)).collider).gameObject;
string text = (((Object)(object)gameObject != (Object)null) ? (((Object)gameObject).name ?? string.Empty) : string.Empty);
string text2 = text.ToLowerInvariant();
if ((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Heightmap>() != (Object)null)
{
return true;
}
if (text2.Contains("terrain") || text2.Contains("heightmap") || text2.Contains("ground"))
{
return true;
}
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[GROUND] Elutasítva: nem valódi talaj. collider=" + text + " layer=" + LayerMask.LayerToName(gameObject.layer)));
}
return false;
}
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_0038: 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_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: 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_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: 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_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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_012d: 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_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
snapped = position;
if (!GroundSnapToTerrain.Value)
{
return true;
}
float num = Mathf.Max(1f, GroundSnapRayHeight.Value);
Vector3 val = position + Vector3.up * num;
float num2 = num * 2f + 20f;
RaycastHit[] array = Physics.RaycastAll(new Ray(val, Vector3.down), num2, -1, (QueryTriggerInteraction)1);
if (array == null || array.Length == 0)
{
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[GROUND] Nincs raycast találat: " + Vec(position)));
}
return !RequireRealGroundHit.Value;
}
Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
for (int i = 0; i < array.Length; i++)
{
RaycastHit hit = array[i];
if (IsValidPlantingGroundHit(hit))
{
snapped = new Vector3(position.x, ((RaycastHit)(ref hit)).point.y, position.z);
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[GROUND] valid hit=" + (((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) ? ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name : "null") + " | from=" + Vec(position) + " -> " + Vec(snapped)));
}
return true;
}
}
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[GROUND] Nem talált valódi talajt ezen a ponton: " + Vec(position)));
}
return !RequireRealGroundHit.Value;
}
internal static Vector3 SnapToGround(Vector3 position)
{
//IL_0016: 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_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if (!UseGroundRaySnap.Value)
{
return position;
}
if (TrySnapToGround(position, out var snapped))
{
return snapped;
}
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 IsIgnoredPlacementCollider(Collider hit)
{
if ((Object)(object)hit == (Object)null || (Object)(object)((Component)hit).gameObject == (Object)null)
{
return true;
}
string text = ((Object)((Component)hit).gameObject).name ?? string.Empty;
if (text.Length == 0)
{
return true;
}
return 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;
}
internal static bool IsExistingPlantCollider(Collider hit)
{
if ((Object)(object)hit == (Object)null || (Object)(object)((Component)hit).gameObject == (Object)null)
{
return false;
}
GameObject gameObject = ((Component)hit).gameObject;
string text = ((Object)gameObject).name ?? string.Empty;
if (text.IndexOf("PlantingPreview", StringComparison.OrdinalIgnoreCase) >= 0)
{
return false;
}
if (text.IndexOf("ghost", StringComparison.OrdinalIgnoreCase) >= 0)
{
return false;
}
if (text.IndexOf("vfx", StringComparison.OrdinalIgnoreCase) >= 0)
{
return false;
}
if (text.IndexOf("terrain", StringComparison.OrdinalIgnoreCase) >= 0)
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Player>() != (Object)null)
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Plant>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Pickable>() != (Object)null && (IsSmallPlantName(text) || IsTreePlantName(text) || IsPlantPlacement(gameObject)))
{
return true;
}
if (IsSmallPlantName(text) || IsTreePlantName(text) || IsPlantPlacement(gameObject))
{
return true;
}
Transform root = gameObject.transform.root;
if ((Object)(object)root != (Object)null)
{
string name = ((Object)((Component)root).gameObject).name ?? string.Empty;
if (IsSmallPlantName(name) || IsTreePlantName(name) || IsPlantPlacement(((Component)root).gameObject))
{
return true;
}
}
return false;
}
internal static bool IsInsidePreviewRoot(Collider hit)
{
if ((Object)(object)hit == (Object)null)
{
return false;
}
Transform val = ((Component)hit).transform;
while ((Object)(object)val != (Object)null)
{
string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? (((Object)((Component)val).gameObject).name ?? string.Empty) : string.Empty);
if (text.IndexOf("PlantingPreview", StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
val = val.parent;
}
return false;
}
internal static bool ExistingPlantIsOutsideOnThisGridEdge(Vector3 candidatePosition, Vector3 plantPosition, Vector2Int cell, Vector3 right, Vector3 forward)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = plantPosition - candidatePosition;
val.y = 0f;
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
return true;
}
bool flag = false;
bool flag2 = false;
if (((Vector2Int)(ref cell)).x > 0)
{
flag = true;
flag2 |= Vector3.Dot(val, right) > 0.05f;
}
else if (((Vector2Int)(ref cell)).x < 0)
{
flag = true;
flag2 |= Vector3.Dot(val, right) < -0.05f;
}
if (((Vector2Int)(ref cell)).y > 0)
{
flag = true;
flag2 |= Vector3.Dot(val, forward) > 0.05f;
}
else if (((Vector2Int)(ref cell)).y < 0)
{
flag = true;
flag2 |= Vector3.Dot(val, forward) < -0.05f;
}
return !flag || flag2;
}
internal static bool IsNearbyObjectBlockingPlantGrowth(Collider hit)
{
if ((Object)(object)hit == (Object)null || (Object)(object)((Component)hit).gameObject == (Object)null)
{
return false;
}
if (IsInsidePreviewRoot(hit))
{
return false;
}
if (IsIgnoredPlacementCollider(hit))
{
return false;
}
if (IsExistingPlantCollider(hit))
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Player>() != (Object)null)
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Character>() != (Object)null)
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<ItemDrop>() != (Object)null)
{
return false;
}
GameObject gameObject = ((Component)hit).gameObject;
string text = ((Object)gameObject).name ?? string.Empty;
string text2 = text.ToLowerInvariant();
if (text2.Contains("heightmap") || text2.Contains("terrain") || text2.Contains("ground"))
{
return false;
}
if (text2.Contains("water"))
{
return false;
}
if (text2.Contains("leviathan"))
{
return false;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Piece>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<WearNTear>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<StaticPhysics>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Container>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<Door>() != (Object)null)
{
return true;
}
if ((Object)(object)((Component)hit).GetComponentInParent<ZNetView>() != (Object)null)
{
return true;
}
return true;
}
internal static bool HasNearbyObjectTooCloseForGrowth(Vector3 position, float spacing)
{
//IL_0044: 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)
if (!CheckNearbyObjectsForGrowthSpace.Value)
{
return false;
}
float num = Mathf.Clamp(spacing * Mathf.Clamp(NearbyObjectCheckMultiplier.Value, 0.1f, 2f), 0.1f, 10f);
Collider[] array = Physics.OverlapSphere(position, num, -1, (QueryTriggerInteraction)1);
foreach (Collider val in array)
{
if (IsNearbyObjectBlockingPlantGrowth(val))
{
if (DebugEnabled.Value && DebugCollisionCheck.Value)
{
string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : "null");
Log.LogInfo((object)("[OBJECT BLOCK] Tereptárgy/építmény túl közel a növekedési helyhez. pos=" + Vec(position) + " radius=" + num.ToString("0.###") + " hit=" + text));
}
return true;
}
}
return false;
}
internal static bool HasExistingPlantTooClose(Vector3 position, float spacing)
{
//IL_0001: 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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
return HasExistingPlantTooCloseOnGridEdge(position, spacing, Vector2Int.zero, Vector3.right, Vector3.forward, useEdgeDirection: false);
}
internal static bool HasExistingPlantTooCloseOnGridEdge(Vector3 position, float spacing, Vector2Int cell, Vector3 right, Vector3 forward, bool useEdgeDirection)
{
//IL_0044: 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_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: 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)
if (!CheckExistingPlants.Value)
{
return false;
}
float num = Mathf.Clamp(spacing * Mathf.Clamp(ExistingPlantCheckMultiplier.Value, 0.2f, 2f), 0.2f, 10f);
Collider[] array = Physics.OverlapSphere(position, num, -1, (QueryTriggerInteraction)1);
foreach (Collider val in array)
{
if (IsInsidePreviewRoot(val) || !IsExistingPlantCollider(val))
{
continue;
}
Vector3 plantPosition = (((Object)(object)((Component)val).transform != (Object)null) ? ((Component)val).transform.position : position);
Vector2Int val2;
if (useEdgeDirection && !ExistingPlantIsOutsideOnThisGridEdge(position, plantPosition, cell, right, forward))
{
if (DebugEnabled.Value && DebugCollisionCheck.Value)
{
string text = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : "null");
ManualLogSource log = Log;
string[] obj = new string[6] { "[PLANT EDGE IGNORE] Meglévő növény közel van, de nem ezen a rács-szélen. cell=", null, null, null, null, null };
val2 = cell;
obj[1] = ((object)(Vector2Int)(ref val2)).ToString();
obj[2] = " pos=";
obj[3] = Vec(position);
obj[4] = " hit=";
obj[5] = text;
log.LogInfo((object)string.Concat(obj));
}
continue;
}
if (DebugEnabled.Value && DebugCollisionCheck.Value)
{
string text2 = (((Object)(object)((Component)val).gameObject != (Object)null) ? ((Object)((Component)val).gameObject).name : "null");
ManualLogSource log2 = Log;
string[] obj2 = new string[8] { "[PLANT BLOCK] Meglévő növény túl közel a rács szélén. cell=", null, null, null, null, null, null, null };
val2 = cell;
obj2[1] = ((object)(Vector2Int)(ref val2)).ToString();
obj2[2] = " pos=";
obj2[3] = Vec(position);
obj2[4] = " radius=";
obj2[5] = num.ToString("0.###");
obj2[6] = " hit=";
obj2[7] = text2;
log2.LogInfo((object)string.Concat(obj2));
}
return true;
}
return false;
}
internal static bool CanPlaceAt(Vector3 position, float spacing)
{
//IL_0001: 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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
return CanPlaceAt(position, spacing, Vector2Int.zero, Vector3.right, Vector3.forward, useEdgeDirection: false);
}
internal static bool CanPlaceAt(Vector3 position, float spacing, Vector2Int cell, Vector3 right, Vector3 forward, bool useEdgeDirection)
{
//IL_0053: 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_0056: 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_00ae: 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_003a: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: 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;
}
if (HasExistingPlantTooCloseOnGridEdge(position, spacing, cell, right, forward, useEdgeDirection))
{
if (DebugEnabled.Value && DebugCollisionCheck.Value)
{
Log.LogInfo((object)("[COLLISION] Eredmény pozíción " + Vec(position) + " -> blocked=true, reason=existing plant edge"));
}
return false;
}
if (HasNearbyObjectTooCloseForGrowth(position, spacing))
{
if (DebugEnabled.Value && DebugCollisionCheck.Value)
{
Log.LogInfo((object)("[COLLISION] Eredmény pozíción " + Vec(position) + " -> blocked=true, reason=nearby object growth space"));
}
return false;
}
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 = IsIgnoredPlacementCollider(val);
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, float spacing)
{
//IL_0001: 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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
return CanPreviewPlaceAt(position, spacing, Vector2Int.zero, Vector3.right, Vector3.forward, useEdgeDirection: false);
}
internal static bool CanPreviewPlaceAt(Vector3 position, float spacing, Vector2Int cell, Vector3 right, Vector3 forward, bool useEdgeDirection)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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_0030: 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)
if (!ExtraPlacementRequiresFreeSpace.Value)
{
return true;
}
if (HasExistingPlantTooCloseOnGridEdge(position, spacing, cell, right, forward, useEdgeDirection))
{
return false;
}
if (HasNearbyObjectTooCloseForGrowth(position, spacing))
{
return false;
}
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) && !IsIgnoredPlacementCollider(val))
{
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 int LimitExtraCountByResources(Player player, Piece piece, int requestedExtra, bool reserveVanillaCenterCost)
{
if (requestedExtra <= 0)
{
return 0;
}
if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null || piece.m_resources == null || piece.m_resources.Length == 0)
{
return requestedExtra;
}
Inventory inventory = ((Humanoid)player).GetInventory();
if (inventory == null)
{
return 0;
}
int num = requestedExtra;
for (int i = 0; i < piece.m_resources.Length; i++)
{
Requirement val = piece.m_resources[i];
if (val != null && !((Object)(object)val.m_resItem == (Object)null) && val.m_amount > 0)
{
string name = val.m_resItem.m_itemData.m_shared.m_name;
int num2 = inventory.CountItems(name, -1, true);
if (reserveVanillaCenterCost)
{
num2 -= val.m_amount;
}
int num3 = Mathf.Max(0, num2) / val.m_amount;
num = Mathf.Min(num, num3);
}
}
return Mathf.Clamp(num, 0, requestedExtra);
}
internal static List<Vector3> CalculateExtraPositions(Player player, GameObject sourceGhost, Piece selectedPiece)
{
//IL_008d: 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_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: 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_00e5: 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_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: 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_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: 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_01ca: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0205: Unknown result type (might be due to invalid IL or missing references)
//IL_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
//IL_02af: Unknown result type (might be due to invalid IL or missing references)
//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_023e: Unknown result type (might be due to invalid IL or missing references)
//IL_0243: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: 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)
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_0347: Unknown result type (might be due to invalid IL or missing references)
//IL_03a4: 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_03ae: Unknown result type (might be due to invalid IL or missing references)
//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
//IL_03b5: 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_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_0425: Unknown result type (might be due to invalid IL or missing references)
//IL_042c: Unknown result type (might be due to invalid IL or missing references)
//IL_0460: Unknown result type (might be due to invalid IL or missing references)
//IL_044e: Unknown result type (might be due to invalid IL or missing references)
//IL_040c: Unknown result type (might be due to invalid IL or missing references)
//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
CachedExtraPositions.Clear();
CachedExtraCells.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);
extraPlantCount = LimitExtraCountByResources(player, selectedPiece, extraPlantCount, reserveVanillaCenterCost: true);
if (extraPlantCount <= 0)
{
LogGhost("CalculateExtraPositions: extraCount <= 0, nincs extra pozíció.");
return CachedExtraPositions;
}
float spacingForSelectedPlant = GetSpacingForSelectedPlant(player, sourceGhost, selectedPiece);
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>();
List<Vector2Int> list2 = new List<Vector2Int>();
if (UseSquarePattern.Value)
{
List<Vector2Int> list3 = 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 < list3.Count; i++)
{
Vector2Int item = list3[i];
list.Add((val * (float)((Vector2Int)(ref item)).x + val2 * (float)((Vector2Int)(ref item)).y) * spacingForSelectedPlant);
list2.Add(item);
}
}
else
{
Vector3 val3;
if (!SnapUseGhostRight.Value)
{
Vector3 right = ((Component)player).transform.right;
val3 = ((Vector3)(ref right)).normalized;
}
else
{
val3 = val;
}
Vector3 val4 = val3;
List<int> list4 = BuildOffsetPattern(extraPlantCount);
for (int j = 0; j < list4.Count; j++)
{
list.Add(val4 * ((float)list4[j] * spacingForSelectedPlant));
list2.Add(new Vector2Int(list4[j], 0));
}
}
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[POS] origin=" + Vec(position) + " spacing=" + spacingForSelectedPlant + " extraCount=" + extraPlantCount + " square=" + UseSquarePattern.Value));
}
for (int k = 0; k < list.Count; k++)
{
Vector3 val5 = position + list[k];
Vector3 val6 = val5;
bool flag = false;
if (TrySnapToGround(val5, out var snapped))
{
val6 = snapped;
flag = true;
Vector3 val7 = val6;
CachedExtraPositions.Add(val7);
if (k < list2.Count)
{
CachedExtraCells.Add(list2[k]);
}
else
{
CachedExtraCells.Add(Vector2Int.zero);
}
if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[POS] idx=" + k + " raw=" + Vec(val5) + " terrainHit=" + flag + " final=" + Vec(val7)));
}
}
else if (DebugEnabled.Value && DebugShowPositionDetails.Value)
{
Log.LogInfo((object)("[POS] idx=" + k + " kihagyva, mert nincs valódi talaj. raw=" + Vec(val5)));
}
}
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_02d5: Unknown result type (might be due to invalid IL or missing references)
//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_031d: Unknown result type (might be due to invalid IL or missing references)
//IL_0322: Unknown result type (might be due to invalid IL or missing references)
//IL_0338: Unknown result type (might be due to invalid IL or missing references)
//IL_033d: Unknown result type (might be due to invalid IL or missing references)
//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0400: Unknown result type (might be due to invalid IL or missing references)
//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
//IL_02c4: 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);
if (text.StartsWith("HH_", StringComparison.OrdinalIgnoreCase))
{
HidePreviewGhosts();
return;
}
int extraPlantCount = GetExtraPlantCount(player);
bool flag = HasCultivatorEquipped(player, placementGhost);
Piece selectedPieceSafe = GetSelectedPieceSafe(player);
GameObject val = (((Object)(object)selectedPieceSafe != (Object)null) ? ((Component)selectedPieceSafe).gameObject : null);
bool flag2 = IsPlantPlacement(placementGhost) || IsPlantPlacement(val);
bool flag3 = (IsPlantableGhost(placementGhost) || IsPlantableGhost(val)) && 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;
}
Piece selectedPiece = selectedPieceSafe;
string plantKey = GetPlantKey(placementGhost, selectedPiece);
if (plantKey != _lastSelectedPlantKey)
{
LogGhost("Kiválasztott növény változott: " + _lastSelectedPlantKey + " -> " + plantKey + ". Preview újraépítés.");
DestroyPreviewGhosts();
_lastSelectedPlantKey = plantKey;
}
List<Vector3> list = CalculateExtraPositions(player, placementGhost, selectedPiece);
EnsurePreviewGhostCount(list.Count, player, placementGhost);
Quaternion previewRotation = GetPreviewRotation(placementGhost);
float spacingForSelectedPlant = GetSpacingForSelectedPlant(player, placementGhost, selectedPiece);
if (_hasStickyRotation)
{
try
{
placementGhost.transform.rotation = previewRotation;
}
catch
{
}
}
Vector3 right = previewRotation * Vector3.right;
Vector3 forward = previewRotation * Vector3.forward;
right.y = 0f;
forward.y = 0f;
if (((Vector3)(ref right)).sqrMagnitude < 0.0001f)
{
right = Vector3.right;
}
if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f)
{
forward = Vector3.forward;
}
((Vector3)(ref right)).Normalize();
((Vector3)(ref forward)).Normalize();
for (int i = 0; i < PreviewGhosts.Count; i++)
{
GameObject val2 = PreviewGhosts[i];
if ((Object)(object)val2 == (Object)null)
{
continue;
}
if (i >= list.Count)
{
val2.SetActive(false);
continue;
}
Vector2Int cell = ((i < CachedExtraCells.Count) ? CachedExtraCells[i] : Vector2Int.zero);
bool valid = CanPreviewPlaceAt(list[i], spacingForSelectedPlant, cell, right, forward, useEdgeDirection: true);
Vector3 val3 = list[i] + Vector3.up * 0.08f;
val2.transform.SetPositionAndRotation(val3, previewRotation);
SetPreviewValidState(val2, valid);
if (!val2.activeSelf)
{
val2.SetActive(true);
}
if (!DebugEnabled.Value || !DebugGhostUpdate.Value || !DebugShowPositionDetails.Value)
{
continue;
}
Renderer[] componentsInChildren = val2.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=" + val2.activeSelf));
}
_lastPreviewVisible = true;
}
internal static void PlaceExtraPlants(Player player, Piece piece, Quaternion rot)
{
//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
//IL_0475: Unknown result type (might be due to invalid IL or missing references)
//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
//IL_0307: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
//IL_030c: Unknown result type (might be due to invalid IL or missing references)
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
//IL_0312: Unknown result type (might be due to invalid IL or missing references)
//IL_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_0316: Unknown result type (might be due to invalid IL or missing references)
//IL_033f: Unknown result type (might be due to invalid IL or missing references)
//IL_0359: Unknown result type (might be due to invalid IL or missing references)
//IL_035b: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: 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_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_0217: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_0255: Unknown result type (might be due to invalid IL or missing references)
//IL_026b: 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)
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;
}
GameObject gameObject = ((Component)piece).gameObject;
bool flag = IsPlantableGhost(placementGhost) && IsPlantPlacement(placementGhost);
bool flag2 = (Object)(object)gameObject != (Object)null && IsPlantableGhost(gameObject) && IsPlantPlacement(gameObject);
if (!flag && !flag2)
{
LogPlacement("PlaceExtraPlants megszakítva: sem a placement ghost, sem a selected piece nem támogatott növény. ghost=" + CleanName(((Object)placementGhost).name) + " piece=" + (((Object)(object)gameObject != (Object)null) ? CleanName(((Object)gameObject).name) : "null"));
return;
}
if ((Object)(object)gameObject == (Object)null)
{
LogPlacement("PlaceExtraPlants megszakítva: piece.gameObject null.");
return;
}
CalculateExtraPositions(player, placementGhost, piece);
float spacingForSelectedPlant = GetSpacingForSelectedPlant(player, placementGhost, piece);
if (CachedExtraPositions.Count <= 0)
{
LogPlacement("PlaceExtraPlants megszakítva: nincs extra pozíció újraszámolás után.");
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"));
Vector3 right = rot * Vector3.right;
Vector3 forward = rot * Vector3.forward;
right.y = 0f;
forward.y = 0f;
if (((Vector3)(ref right)).sqrMagnitude < 0.0001f)
{
right = Vector3.right;
}
if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f)
{
forward = Vector3.forward;
}
((Vector3)(ref right)).Normalize();
((Vector3)(ref forward)).Normalize();
int num = 0;
int num2 = 0;
int num3 = LimitExtraCountByResources(player, piece, CachedExtraPositions.Count, reserveVanillaCenterCost: false);
for (int i = 0; i < CachedExtraPositions.Count; i++)
{
if (num >= num3)
{
LogPlacement("Extra lerakás megállítva mag limit miatt. placed=" + num + " max=" + num3);
break;
}
Vector3 val = CachedExtraPositions[i];
Vector2Int cell = ((i < CachedExtraCells.Count) ? CachedExtraCells[i] : Vector2Int.zero);
if (!CanPlaceAt(val, spacingForSelectedPlant, cell, right, forward, useEdgeDirection: true))
{
num2++;
LogPla