Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RestlessPlant v0.2.4
RestlessPlant.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using RestlessQoL.Api; using RestlessQoL.Core; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RestlessPlant")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.4.0")] [assembly: AssemblyInformationalVersion("0.2.4+0066ffe24731b87d32b95e138a0eb30db8fbf5eb")] [assembly: AssemblyProduct("RestlessPlant")] [assembly: AssemblyTitle("RestlessPlant")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RestlessPlant { internal enum CropGate { Forage, Sapling, Flora } internal readonly struct CropRow { public string Source { get; } public string Item { get; } public string Name { get; } public string Description { get; } public CropGate Gate { get; } public bool Till { get; } public bool Attach { get; } public string Prefab => "Restless_" + Source; public CropRow(string source, string item, string name, string description, CropGate gate = CropGate.Forage, bool till = true, bool attach = false) { Source = source; Item = item; Name = name; Description = description; Gate = gate; Till = till; Attach = attach; } } internal static class CropBook { public static readonly IReadOnlyList<CropRow> Rows = new CropRow[32] { new CropRow("RaspberryBush", "Raspberry", "Raspberry bush", "Plant a raspberry bush."), new CropRow("BlueberryBush", "Blueberries", "Blueberry bush", "Plant a blueberry bush."), new CropRow("CloudberryBush", "Cloudberry", "Cloudberry bush", "Plant a cloudberry bush."), new CropRow("LingonberryBush", "Lingonberry", "Lingonberry bush", "Plant a lingonberry bush."), new CropRow("Pickable_Mushroom", "Mushroom", "Mushroom", "Plant mushrooms."), new CropRow("Pickable_Mushroom_yellow", "MushroomYellow", "Yellow mushroom", "Plant yellow mushrooms."), new CropRow("Pickable_Mushroom_blue", "MushroomBlue", "Blue mushroom", "Plant blue mushrooms."), new CropRow("Pickable_Thistle", "Thistle", "Thistle", "Plant thistle."), new CropRow("Pickable_Dandelion", "Dandelion", "Dandelion", "Plant dandelion."), new CropRow("Pickable_Mushroom_Magecap", "MushroomMagecap", "Magecap", "Plant magecap."), new CropRow("Pickable_Mushroom_JotunPuffs", "MushroomJotunPuffs", "Jotun puffs", "Plant jotun puffs."), new CropRow("Pickable_SmokePuff", "MushroomSmokePuff", "Smoke puff", "Plant smoke puff."), new CropRow("Pickable_Fiddlehead", "Fiddleheadfern", "Fiddlehead", "Plant fiddlehead."), new CropRow("Beech_Sapling", "BeechSeeds", "Beech sapling", "Plant a beech sapling.", CropGate.Sapling, till: false), new CropRow("PineTree_Sapling", "PineCone", "Pine sapling", "Plant a pine sapling.", CropGate.Sapling, till: false), new CropRow("FirTree_Sapling", "FirCone", "Fir sapling", "Plant a fir sapling.", CropGate.Sapling, till: false), new CropRow("Birch_Sapling", "BirchSeeds", "Birch sapling", "Plant a birch sapling.", CropGate.Sapling, till: false), new CropRow("Oak_Sapling", "Acorn", "Oak sapling", "Plant an oak sapling.", CropGate.Sapling, till: false), new CropRow("Beech_small1", "Wood", "Small beech", "Plant a small beech.", CropGate.Flora, till: false), new CropRow("FirTree_small", "Wood", "Small fir", "Plant a small fir.", CropGate.Flora, till: false), new CropRow("FirTree_small_dead", "Wood", "Small dead fir", "Plant a small dead fir.", CropGate.Flora, till: false), new CropRow("Bush01", "Wood", "Small bush", "Plant a small bush.", CropGate.Flora, till: false), new CropRow("Bush01_heath", "Wood", "Heath bush", "Plant a heath bush.", CropGate.Flora, till: false), new CropRow("Bush02_en", "Wood", "Fruitless bush", "Plant a fruitless bush.", CropGate.Flora, till: false), new CropRow("shrub_2", "Wood", "Small shrub", "Plant a small shrub.", CropGate.Flora, till: false), new CropRow("shrub_2_heath", "Wood", "Heath shrub", "Plant a heath shrub.", CropGate.Flora, till: false), new CropRow("YggaShoot_small1", "YggdrasilWood", "Ygga shoot", "Plant a small ygga shoot.", CropGate.Flora, till: false), new CropRow("vines", "Wood", "Vines", "Plant wall vines.", CropGate.Flora, till: false, attach: true), new CropRow("FernAshlands", "Wood", "Ashlands fern", "Plant an Ashlands fern.", CropGate.Flora, till: false), new CropRow("Pickable_Branch", "Wood", "Branch", "Place a pickable branch.", CropGate.Flora, till: false), new CropRow("Pickable_Stone", "Stone", "Stone", "Place a pickable stone.", CropGate.Flora, till: false), new CropRow("Pickable_Flint", "Flint", "Flint", "Place a pickable flint.", CropGate.Flora, till: false) }; public static bool Allowed(CropRow row) { return row.Gate switch { CropGate.Sapling => PlantConfig.ExtraSaplings.Value, CropGate.Flora => PlantConfig.ExtraFlora.Value, _ => PlantConfig.ExtraCrops.Value, }; } public static bool IsOurs(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } return prefabName.StartsWith("Restless_"); } } internal static class CropPieces { private const float DefaultRespawnMinutes = 240f; private static bool _added; public static void Load() { PrefabManager.OnVanillaPrefabsAvailable += Add; } private static void Add() { //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Add; if (_added) { return; } _added = true; if (!PlantConfig.On) { return; } Piece val = TemplatePiece(); int num = 0; foreach (CropRow row in CropBook.Rows) { if (!CropBook.Allowed(row)) { continue; } GameObject prefab = PrefabManager.Instance.GetPrefab(row.Source); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no vanilla prefab).")); continue; } string text = ItemOf(row, prefab); if (text == null) { Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no item " + row.Item + ").")); continue; } Sprite val2 = IconOf(text); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no icon on " + text + ").")); continue; } GameObject val3 = PrefabManager.Instance.CreateClonedPrefab(row.Prefab, row.Source); if (!((Object)(object)val3 == (Object)null)) { Renderer[] componentsInChildren = val3.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj in componentsInChildren) { ((Component)obj).gameObject.SetActive(true); obj.enabled = true; } Piece val4 = val3.GetComponent<Piece>() ?? val3.AddComponent<Piece>(); bool value = PlantConfig.GrowAnywhere.Value; val4.m_groundOnly = !row.Attach && !value; val4.m_groundPiece = !row.Attach; val4.m_allowAltGroundPlacement = value; val4.m_noInWater = !value; val4.m_cultivatedGroundOnly = row.Till && !value; val4.m_icon = val2; val4.m_canBeRemoved = true; if ((Object)(object)val != (Object)null) { CopyPlacement(val4, val); } SitOnPieceLayer(val3); FlattenLod(val3); TunePickable(prefab, val3); PieceConfig val5 = new PieceConfig { Name = row.Name, Description = row.Description, PieceTable = PieceTables.Cultivator, CraftingStation = CraftingStations.None, Icon = val2 }; val5.AddRequirement(text, 1, true); PieceManager.Instance.AddPiece(new CustomPiece(val3, true, val5)); num++; } } Plugin.Log.LogInfo((object)$"RestlessPlant added {num} cultivator crops."); } private static Piece? TemplatePiece() { string[] array = new string[3] { "sapling_carrot", "Plant_Carrot", "CarrotSeeds" }; foreach (string text in array) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void SitOnPieceLayer(GameObject go) { int num = LayerMask.NameToLayer("piece"); if (num >= 0) { Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Component)componentsInChildren[i]).gameObject.layer = num; } } } private static void CopyPlacement(Piece dest, Piece src) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) dest.m_placeEffect = src.m_placeEffect; dest.m_category = src.m_category; } private static void FlattenLod(GameObject go) { LODGroup[] componentsInChildren = go.GetComponentsInChildren<LODGroup>(true); foreach (LODGroup val in componentsInChildren) { LOD[] lODs = val.GetLODs(); Renderer[] array = ((lODs.Length != 0) ? lODs[0].renderers : null); Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { val2.enabled = array == null || Array.IndexOf(array, val2) >= 0; } } val.enabled = false; Object.DestroyImmediate((Object)(object)val); } } private static void TunePickable(GameObject source, GameObject clone) { Pickable componentInChildren = source.GetComponentInChildren<Pickable>(true); Pickable componentInChildren2 = clone.GetComponentInChildren<Pickable>(true); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren2 == (Object)null)) { componentInChildren2.m_respawnTimeMinutes = componentInChildren.m_respawnTimeMinutes; componentInChildren2.m_amount = componentInChildren.m_amount; if (componentInChildren2.m_respawnTimeMinutes <= 0f) { componentInChildren2.m_respawnTimeMinutes = 240f; } } } private static string? ItemOf(CropRow row, GameObject source) { if ((Object)(object)PrefabManager.Instance.GetPrefab(row.Item) != (Object)null) { return row.Item; } Pickable componentInChildren = source.GetComponentInChildren<Pickable>(true); if ((Object)(object)componentInChildren?.m_itemPrefab == (Object)null) { return null; } return Utils.GetPrefabName(componentInChildren.m_itemPrefab); } private static Sprite? IconOf(string item) { GameObject prefab = PrefabManager.Instance.GetPrefab(item); ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { return null; } try { return val.m_itemData.GetIcon(); } catch { Sprite[] array = val.m_itemData?.m_shared?.m_icons; return (array != null && array.Length > 0) ? array[0] : null; } } } internal static class PlantConfig { private static readonly ConfigurationManagerAttributes Admin = new ConfigurationManagerAttributes { IsAdminOnly = true }; private static readonly ConfigurationManagerAttributes Hidden = new ConfigurationManagerAttributes { Browsable = false }; public static ConfigEntry<bool> Enabled = null; public static ConfigEntry<bool> ExtraCrops = null; public static ConfigEntry<bool> ExtraSaplings = null; public static ConfigEntry<bool> ExtraFlora = null; public static ConfigEntry<bool> GrowAnywhere = null; public static ConfigEntry<bool> Grid = null; public static ConfigEntry<int> GridColumns = null; public static ConfigEntry<int> GridRows = null; public static ConfigEntry<float> Spacing = null; public static ConfigEntry<bool> SnapToField = null; public static ConfigEntry<float> SnapRange = null; public static ConfigEntry<bool> BulkHarvest = null; public static ConfigEntry<bool> BulkBeehives = null; public static ConfigEntry<float> HarvestRange = null; public static ConfigEntry<bool> Replant = null; public static ConfigEntry<bool> RegrowHint = null; public static ConfigEntry<KeyboardShortcut> ColsUp = null; public static ConfigEntry<KeyboardShortcut> ColsDown = null; public static ConfigEntry<KeyboardShortcut> RowsUp = null; public static ConfigEntry<KeyboardShortcut> RowsDown = null; public static ConfigEntry<KeyboardShortcut> SnapToggle = null; public static bool On => Enabled.Value; public static void Bind(ConfigFile config) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Expected O, but got Unknown //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Expected O, but got Unknown //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Expected O, but got Unknown //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Expected O, but got Unknown //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Expected O, but got Unknown //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>("Plant", "Enabled", true, new ConfigDescription("Cultivator extras, grid planting, and bulk harvest. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); ExtraCrops = config.Bind<bool>("Plant", "BerryBushesAndForage", true, new ConfigDescription("Add berry bushes, mushrooms, thistle, and later-biome forage to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); ExtraSaplings = config.Bind<bool>("Plant", "ExtraSaplings", true, new ConfigDescription("Add beech, pine, fir, birch, and oak saplings to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); ExtraFlora = config.Bind<bool>("Plant", "DecorativeTrees", true, new ConfigDescription("Add small trees, shrubs, vines, and stick/stone/flint pickables to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); GrowAnywhere = config.Bind<bool>("Plant", "GrowAnywhere", false, new ConfigDescription("Skip tilled ground, biome, sun, and space checks so plants can sit on floors and wild soil. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); Grid = config.Bind<bool>("Grid", "Enabled", true, "Plant a rectangle of the selected cultivator piece. Client-local size."); ConfigEntry<int> val = config.Bind<int>("Plant", "GridSize", 1, new ConfigDescription("Obsolete. Copied once into GridColumns and GridRows.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { Hidden })); GridColumns = config.Bind<int>("Grid", "Columns", 1, new ConfigDescription("How many plants wide. [ ] resize.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), Array.Empty<object>())); GridRows = config.Bind<int>("Grid", "Rows", 1, new ConfigDescription("How many plants deep. - = resize.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), Array.Empty<object>())); if (GridColumns.Value == 1 && GridRows.Value == 1 && val.Value > 1) { GridColumns.Value = val.Value; GridRows.Value = val.Value; } Spacing = config.Bind<float>("Grid", "Spacing", 0f, new ConfigDescription("Minimum metres between plants. 0 uses the space that crop needs to grow. A crop that needs more room still uses that.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>())); ConfigEntry<bool> val2 = config.Bind<bool>("Grid", "SpacingFollowsCrop", false, new ConfigDescription("Internal. The old 2m spacing default was cleared once.", (AcceptableValueBase)null, new object[1] { Hidden })); if (!val2.Value) { if (Mathf.Abs(Spacing.Value - 2f) < 0.01f) { Spacing.Value = 0f; } val2.Value = true; } SnapToField = config.Bind<bool>("Grid", "SnapToField", true, "Snap the cultivator ghost onto a nearby plant's spacing. Client-local."); SnapRange = config.Bind<float>("Grid", "SnapRange", 3f, new ConfigDescription("How far to look for a plant to snap to, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>())); BulkHarvest = config.Bind<bool>("Harvest", "BulkHarvest", true, new ConfigDescription("Picking a player-grown plant also picks every ripe player-grown crop in range, not only the same kind. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); BulkBeehives = config.Bind<bool>("Harvest", "BulkBeehives", true, new ConfigDescription("Using a beehive also takes honey from matching neighbours. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); HarvestRange = config.Bind<float>("Harvest", "HarvestRange", 2.5f, new ConfigDescription("Bulk-harvest radius for plants and hives.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f), new object[1] { Admin })); Replant = config.Bind<bool>("Harvest", "ReplantOnHarvest", true, new ConfigDescription("One-shot crops (carrots and the like) replant the picked piece if you can pay for it. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin })); RegrowHint = config.Bind<bool>("Client", "RegrowHint", true, "Show time until fruit or a sapling is ready. Client-local."); ColsUp = config.Bind<KeyboardShortcut>("Client", "GridColumnsBigger", new KeyboardShortcut((KeyCode)93, Array.Empty<KeyCode>()), "Add a column to the planting rectangle. Client-local."); ColsDown = config.Bind<KeyboardShortcut>("Client", "GridColumnsSmaller", new KeyboardShortcut((KeyCode)91, Array.Empty<KeyCode>()), "Remove a column from the planting rectangle. Client-local."); RowsUp = config.Bind<KeyboardShortcut>("Client", "GridRowsBigger", new KeyboardShortcut((KeyCode)61, Array.Empty<KeyCode>()), "Add a row to the planting rectangle. Client-local."); RowsDown = config.Bind<KeyboardShortcut>("Client", "GridRowsSmaller", new KeyboardShortcut((KeyCode)45, Array.Empty<KeyCode>()), "Remove a row from the planting rectangle. Client-local."); SnapToggle = config.Bind<KeyboardShortcut>("Client", "SnapToggle", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Toggle snap onto an existing field. Client-local."); } } internal static class PlantGrid { private readonly struct Cell { public Vector3 Pos { get; } public bool Ok { get; } public Cell(Vector3 pos, bool ok) { //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) Pos = pos; Ok = ok; } } [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void AfterGhost(Player __instance) { //IL_006e: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) if (_placing) { return; } if (Cultivating(__instance)) { Piece selectedPiece = __instance.GetSelectedPiece(); if ((Object)(object)selectedPiece != (Object)null) { PlantHarvest.Remember(selectedPiece); } } GameObject placementGhost = __instance.m_placementGhost; if ((Object)(object)placementGhost != (Object)null && Cultivating(__instance) && PlantConfig.On && PlantConfig.Grid.Value && Crop(__instance.GetSelectedPiece())) { Align(__instance, placementGhost); } if (!Active(__instance) || ((int)__instance.m_placementStatus != 0 && !PlantGrow.Free)) { Hide(); return; } if ((Object)(object)placementGhost == (Object)null) { Hide(); return; } Piece selectedPiece2 = __instance.GetSelectedPiece(); if ((Object)(object)selectedPiece2 != (Object)(object)_lastPiece) { Clear(); _lastPiece = selectedPiece2; PlantHarvest.Remember(selectedPiece2); } int num = 0; foreach (Cell item in Cells(__instance, placementGhost.transform)) { if (num >= Ghosts.Count || (Object)(object)Ghosts[num] == (Object)null) { GameObject val = MakeGhost(placementGhost, item.Pos, placementGhost.transform.rotation); if (num < Ghosts.Count) { Ghosts[num] = val; } else { Ghosts.Add(val); } } else { Ghosts[num].transform.SetPositionAndRotation(item.Pos, placementGhost.transform.rotation); Ghosts[num].SetActive(true); } Paint(Ghosts[num], item.Ok); num++; } for (int num2 = Ghosts.Count - 1; num2 >= num; num2--) { if ((Object)(object)Ghosts[num2] != (Object)null) { Renderers.Remove(Ghosts[num2]); PaintState.Remove(Ghosts[num2]); Object.Destroy((Object)(object)Ghosts[num2]); } Ghosts.RemoveAt(num2); } if (_lastCols != PlantConfig.GridColumns.Value || _lastRows != PlantConfig.GridRows.Value || _lastSnap != PlantConfig.SnapToField.Value) { _lastCols = PlantConfig.GridColumns.Value; _lastRows = PlantConfig.GridRows.Value; _lastSnap = PlantConfig.SnapToField.Value; ((Character)__instance).Message((MessageType)1, "Plant " + _lastCols + "×" + _lastRows + " [ ] wide - = deep" + (_lastSnap ? " snap" : ""), 0, (Sprite)null, false); } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static void AfterPlace(Player __instance, Piece piece, bool __result) { //IL_0033: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (_placing || !__result || !Active(__instance) || (Object)(object)piece == (Object)null) { return; } GameObject placementGhost = __instance.m_placementGhost; if ((Object)(object)placementGhost == (Object)null) { return; } Quaternion rotation = placementGhost.transform.rotation; int num = ExtraBudget(__instance, piece); int num2 = 0; _placing = true; try { foreach (Cell item in Cells(__instance, placementGhost.transform)) { if (item.Ok) { if (num2 >= num) { break; } __instance.PlacePiece(piece, item.Pos, rotation, false, false); if (!FreeBuild(__instance, piece)) { __instance.ConsumeResources(piece.m_resources, 0, -1, 1); } num2++; } } } finally { _placing = false; } } } private static readonly List<GameObject> Ghosts = new List<GameObject>(); private static readonly Dictionary<GameObject, Renderer[]> Renderers = new Dictionary<GameObject, Renderer[]>(); private static readonly Dictionary<GameObject, bool> PaintState = new Dictionary<GameObject, bool>(); private static GameObject? _probeGhost; private static Collider[] _probeColliders = Array.Empty<Collider>(); private static bool[] _probeEnabled = Array.Empty<bool>(); private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly Color Bad = new Color(1f, 0.35f, 0.35f, 1f); private static Piece? _lastPiece; private static int _lastCols; private static int _lastRows; private static bool _lastSnap; private static bool _placing; private const float GrowGap = 0.1f; private static bool _probeLogged; private static int _fieldMask; public static bool Wide { get { if (PlantConfig.GridColumns.Value <= 1) { return PlantConfig.GridRows.Value > 1; } return true; } } private static int FieldMask { get { if (_fieldMask == 0) { _fieldMask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "item" }); } return _fieldMask; } } public static void Tick() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00ec: 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) if (SettingsPageApi.IsMenuOpen || !PlantConfig.On || !PlantConfig.Grid.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode() || !Cultivating(localPlayer)) { return; } KeyboardShortcut value = PlantConfig.SnapToggle.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { PlantConfig.SnapToField.Value = !PlantConfig.SnapToField.Value; ((Character)localPlayer).Message((MessageType)1, PlantConfig.SnapToField.Value ? "Plant snap on" : "Plant snap off", 0, (Sprite)null, false); _lastSnap = PlantConfig.SnapToField.Value; } value = PlantConfig.ColsUp.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Nudge(PlantConfig.GridColumns, 1, "wide"); return; } value = PlantConfig.ColsDown.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Nudge(PlantConfig.GridColumns, -1, "wide"); return; } value = PlantConfig.RowsUp.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Nudge(PlantConfig.GridRows, 1, "deep"); return; } value = PlantConfig.RowsDown.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Nudge(PlantConfig.GridRows, -1, "deep"); } } private static void Nudge(ConfigEntry<int> entry, int delta, string axis) { int num = Mathf.Clamp(entry.Value + delta, 1, 7); if (num != entry.Value) { entry.Value = num; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Plant " + PlantConfig.GridColumns.Value + "×" + PlantConfig.GridRows.Value + " " + axis, 0, (Sprite)null, false); } _lastCols = PlantConfig.GridColumns.Value; _lastRows = PlantConfig.GridRows.Value; } } public static bool Active(Player player) { if (!PlantConfig.On || !PlantConfig.Grid.Value || (Object)(object)player == (Object)null || !Wide) { return false; } if (Cultivating(player) && Crop(player.GetSelectedPiece())) { return (Object)(object)player.m_placementGhost != (Object)null; } return false; } private static bool Crop(Piece? piece) { if ((Object)(object)piece != (Object)null) { if (!((Object)(object)((Component)piece).GetComponent<Plant>() != (Object)null)) { return (Object)(object)((Component)piece).GetComponentInChildren<Pickable>(true) != (Object)null; } return true; } return false; } public static bool Cultivating(Player player) { PieceTable buildPieces = player.m_buildPieces; if ((Object)(object)buildPieces == (Object)null) { return false; } return (((Object)buildPieces).name ?? "").IndexOf("Cultivator", StringComparison.OrdinalIgnoreCase) >= 0; } private static IEnumerable<Cell> Cells(Player player, Transform ghost) { int cols = Mathf.Clamp(PlantConfig.GridColumns.Value, 1, 7); int rows = Mathf.Clamp(PlantConfig.GridRows.Value, 1, 7); int midX = (cols - 1) / 2; int midZ = (rows - 1) / 2; Piece piece = player.GetSelectedPiece(); float space = Spacing(((Component)ghost).GetComponent<Piece>() ?? piece); Vector3 origin = ghost.position; Vector3 right = Flat(ghost.right); Vector3 fwd = Flat(ghost.forward); Plant plant = ((Component)ghost).GetComponent<Plant>(); for (int z = 0; z < rows; z++) { for (int x = 0; x < cols; x++) { if (x != midX || z != midZ) { Vector3 grounded = origin + (float)(x - midX) * space * right + (float)(z - midZ) * space * fwd; bool flag = Sit(grounded, out grounded); yield return new Cell(grounded, flag && CanGrow(((Component)ghost).gameObject, piece, plant, grounded)); } } } } private static Vector3 Flat(Vector3 axis) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) axis.y = 0f; if (!(((Vector3)(ref axis)).sqrMagnitude > 0.0001f)) { return Vector3.forward; } return ((Vector3)(ref axis)).normalized; } private static float Spacing(Piece? piece) { Plant val = (((Object)(object)piece != (Object)null) ? ((Component)piece).GetComponent<Plant>() : null); float num = 0f; if ((Object)(object)val != (Object)null) { num = val.m_growRadius; if (val.m_growRadiusVines > num) { num = val.m_growRadiusVines; } } float num2 = ((num > 0.05f) ? (num * 2f + 0.1f) : 1f); float value = PlantConfig.Spacing.Value; if (value <= 0.01f) { return num2; } return Mathf.Max(value, num2); } private static bool Sit(Vector3 pos, out Vector3 grounded) { //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_004a: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) grounded = pos; ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return false; } float num = default(float); if (PlantGrow.Free && instance.GetSolidHeight(pos, ref num, 1000)) { grounded = new Vector3(pos.x, num, pos.z); return true; } float num2 = default(float); if (instance.GetGroundHeight(pos, ref num2)) { grounded = new Vector3(pos.x, num2, pos.z); return true; } return false; } private static bool CanGrow(GameObject ghost, Piece? piece, Plant? plant, Vector3 pos) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_006d: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (PlantGrow.Free) { return true; } Heightmap val = Heightmap.FindHeightmap(pos); if ((Object)(object)val == (Object)null) { return false; } if (NeedsTill(piece, plant) && !val.IsCultivated(pos)) { return false; } if ((Object)(object)plant != (Object)null) { return (int)Probe(ghost, plant, pos) == 0; } if ((Object)(object)piece != (Object)null && (int)piece.m_onlyInBiome != 0 && (val.GetBiome(pos, 0.02f, false) & piece.m_onlyInBiome) == 0) { return false; } return !Physics.CheckSphere(pos, 0.4f, Plant.m_spaceMask, (QueryTriggerInteraction)1); } private static bool NeedsTill(Piece? piece, Plant? plant) { if ((Object)(object)plant != (Object)null) { if (!plant.m_needCultivatedGround) { if ((Object)(object)piece != (Object)null) { return piece.m_cultivatedGroundOnly; } return false; } return true; } if (!((Object)(object)piece == (Object)null)) { return piece.m_cultivatedGroundOnly; } return true; } private static Status Probe(GameObject ghost, Plant plant, Vector3 pos) { //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) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Transform transform = ghost.transform; Vector3 position = transform.position; if ((Object)(object)_probeGhost != (Object)(object)ghost) { _probeGhost = ghost; _probeColliders = ghost.GetComponentsInChildren<Collider>(true); _probeEnabled = new bool[_probeColliders.Length]; } Collider[] probeColliders = _probeColliders; bool[] probeEnabled = _probeEnabled; for (int i = 0; i < probeColliders.Length; i++) { if (!((Object)(object)probeColliders[i] == (Object)null)) { probeEnabled[i] = probeColliders[i].enabled; probeColliders[i].enabled = false; } } Status status = plant.m_status; try { transform.position = pos; plant.UpdateHealth(11.0); return plant.GetStatus(); } catch (Exception arg) { if (!_probeLogged) { _probeLogged = true; Plugin.Log.LogWarning((object)$"Plant grow check failed; later cells stay quiet. {arg}"); } return (Status)2; } finally { plant.m_status = status; transform.position = position; for (int j = 0; j < probeColliders.Length; j++) { if ((Object)(object)probeColliders[j] != (Object)null) { probeColliders[j].enabled = probeEnabled[j]; } } } } private static void Align(Player player, GameObject ghost) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0084: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!PlantConfig.SnapToField.Value) { return; } Piece selectedPiece = player.GetSelectedPiece(); float num = Spacing(ghost.GetComponent<Piece>() ?? selectedPiece); Transform val = Field(ghost.transform.position, num, ghost); if ((Object)(object)val == (Object)null) { return; } Vector3 val2 = Flat(val.right); Vector3 val3 = Flat(val.forward); Vector3 val4 = ghost.transform.position - val.position; float num2 = Mathf.Round(Vector3.Dot(val4, val2) / num); float num3 = Mathf.Round(Vector3.Dot(val4, val3) / num); if (Mathf.Abs(num2) < 0.01f && Mathf.Abs(num3) < 0.01f) { float num4 = Vector3.Dot(val4, val2); float num5 = Vector3.Dot(val4, val3); if (Mathf.Abs(num4) >= Mathf.Abs(num5)) { num2 = ((num4 >= 0f) ? 1f : (-1f)); } else { num3 = ((num5 >= 0f) ? 1f : (-1f)); } } if (Sit(val.position + val2 * (num2 * num) + val3 * (num3 * num), out var grounded)) { ghost.transform.SetPositionAndRotation(grounded, Quaternion.LookRotation(val3, Vector3.up)); } } private static Transform? Field(Vector3 from, float space, GameObject ghost) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) float value = PlantConfig.SnapRange.Value; Collider[] array = Physics.OverlapSphere(from, value, FieldMask, (QueryTriggerInteraction)2); Transform result = null; float num = value * value; Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)(object)val == (Object)null) { continue; } Transform val2 = Anchor(val, ghost); if (!((Object)(object)val2 == (Object)null)) { Vector3 val3 = val2.position - from; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (!(sqrMagnitude > num)) { result = val2; num = sqrMagnitude; } } } return result; } private static Transform? Anchor(Collider hit, GameObject ghost) { Plant componentInParent = ((Component)hit).GetComponentInParent<Plant>(); Pickable val = (((Object)(object)componentInParent == (Object)null) ? ((Component)hit).GetComponentInParent<Pickable>() : null); Transform val2 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).transform : (((Object)(object)val != (Object)null) ? ((Component)val).transform : null)); if ((Object)(object)val2 == (Object)null) { return null; } if ((Object)(object)val2 == (Object)(object)ghost.transform || val2.IsChildOf(ghost.transform)) { return null; } if (IsGhost(((Component)val2).gameObject) || IsGhost(((Component)val2.root).gameObject)) { return null; } return val2; } private static bool IsGhost(GameObject go) { if ((Object)(object)go != (Object)null) { return ((Object)go).name.IndexOf("RestlessPlantGhost", StringComparison.Ordinal) >= 0; } return false; } public static void Hide() { foreach (GameObject ghost in Ghosts) { if ((Object)(object)ghost != (Object)null) { ghost.SetActive(false); } } } public static void Clear() { foreach (GameObject ghost in Ghosts) { if (!((Object)(object)ghost == (Object)null)) { ghost.SetActive(false); Object.Destroy((Object)(object)ghost); } } Ghosts.Clear(); Renderers.Clear(); PaintState.Clear(); _probeGhost = null; _probeColliders = Array.Empty<Collider>(); _probeEnabled = Array.Empty<bool>(); _lastPiece = null; } private static GameObject MakeGhost(GameObject source, Vector3 pos, Quaternion rot) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) bool activeSelf = source.activeSelf; source.SetActive(false); GameObject obj = Object.Instantiate<GameObject>(source); source.SetActive(activeSelf); ((Object)obj).name = "RestlessPlantGhost"; obj.transform.SetPositionAndRotation(pos, rot); Strip(obj); obj.SetActive(true); return obj; } private static void Strip(GameObject go) { ZNetView[] componentsInChildren = go.GetComponentsInChildren<ZNetView>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Piece[] componentsInChildren2 = go.GetComponentsInChildren<Piece>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } WearNTear[] componentsInChildren3 = go.GetComponentsInChildren<WearNTear>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } Pickable[] componentsInChildren4 = go.GetComponentsInChildren<Pickable>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } Plant[] componentsInChildren5 = go.GetComponentsInChildren<Plant>(true); for (int i = 0; i < componentsInChildren5.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[i]); } Rigidbody[] componentsInChildren6 = go.GetComponentsInChildren<Rigidbody>(true); for (int i = 0; i < componentsInChildren6.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren6[i]); } Collider[] componentsInChildren7 = go.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren7.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren7[i]); } ReleaseMaterial(go); LODGroup[] componentsInChildren8 = go.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren8.Length; i++) { componentsInChildren8[i].enabled = false; } } private static void ReleaseMaterial(GameObject go) { MaterialMan instance = MaterialMan.instance; MaterialManNotifier[] componentsInChildren = go.GetComponentsInChildren<MaterialManNotifier>(true); foreach (MaterialManNotifier val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { if ((Object)(object)instance != (Object)null) { instance.SetValue<float>(((Component)val).gameObject, 0, 0f, false); } Object.DestroyImmediate((Object)(object)val); } } } private static void Paint(GameObject go, bool ok) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (PaintState.TryGetValue(go, out var value) && value == ok) { return; } PaintState[go] = ok; if (!Renderers.TryGetValue(go, out Renderer[] value2)) { value2 = (Renderers[go] = go.GetComponentsInChildren<Renderer>(true)); } Block.Clear(); Block.SetColor(ColorId, ok ? Color.white : Bad); Renderer[] array = value2; foreach (Renderer val in array) { if ((Object)(object)val != (Object)null) { val.SetPropertyBlock(Block); } } } private static bool FreeBuild(Player player, Piece piece) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (player.m_noPlacementCost) { return true; } if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGlobalKey(piece.FreeBuildKey()); } return false; } private static int ExtraBudget(Player player, Piece piece) { if (FreeBuild(player, piece)) { return int.MaxValue; } int num = int.MaxValue; bool flag = false; Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (val?.m_resItem?.m_itemData?.m_shared != null && val.m_amount > 0) { flag = true; int num2 = (((Humanoid)player).GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true) - val.m_amount) / val.m_amount; if (num2 < num) { num = num2; } } } if (!flag) { return int.MaxValue; } if (num >= 0) { return num; } return 0; } } internal static class PlantGrow { [HarmonyPatch] private static class Patches { private const string ClimbKey = "RestlessClimb"; [HarmonyPrefix] [HarmonyPatch(typeof(Plant), "GetStatus")] private static bool AnyStatus(ref Status __result) { if (!Free) { return true; } __result = (Status)0; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void BeforeGhost(Player __instance) { if (PlantGrid.Cultivating(__instance)) { Relax(__instance.m_placementGhost); } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static void Soften(Piece piece) { if (Free && !((Object)(object)piece == (Object)null)) { _till = piece.m_cultivatedGroundOnly; _ground = piece.m_groundOnly; piece.m_cultivatedGroundOnly = false; piece.m_groundOnly = false; Plant component = ((Component)piece).GetComponent<Plant>(); if (!((Object)(object)component == (Object)null)) { _need = component.m_needCultivatedGround; component.m_needCultivatedGround = false; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static void Harden(Piece piece) { if (Free && !((Object)(object)piece == (Object)null)) { piece.m_cultivatedGroundOnly = _till; piece.m_groundOnly = _ground; Plant component = ((Component)piece).GetComponent<Plant>(); if (!((Object)(object)component == (Object)null)) { component.m_needCultivatedGround = _need; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Plant), "UpdateHealth")] private static void KeepAlive(Plant __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (Free) { __instance.m_status = (Status)0; } else { if ((int)__instance.m_status != 3) { return; } if ((int)__instance.m_biome == 0) { __instance.m_status = (Status)0; return; } Heightmap val = Heightmap.FindHeightmap(((Component)__instance).transform.position); if ((Object)(object)val == (Object)null || (int)val.GetBiome(((Component)__instance).transform.position, 0.02f, false) == 0) { __instance.m_status = (Status)0; } } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Plant), "UpdateHealth")] private static void ClimbRoom(Plant __instance) { if (!Free && Climber(__instance)) { Share(__instance); } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void ClimbGhost(Player __instance) { //IL_000f: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 //IL_006d: 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_0068: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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 (!PlantConfig.On || Free || (int)__instance.m_placementStatus != 0) { return; } Plant val = (((Object)(object)__instance.m_placementGhost != (Object)null) ? __instance.m_placementGhost.GetComponent<Plant>() : null); if ((Object)(object)val == (Object)null || !Climber(val)) { return; } val.UpdateHealth(11.0); Status status = val.GetStatus(); if ((int)status != 0) { PlacementStatus placementStatus = (((int)status == 3) ? ((PlacementStatus)8) : (((int)status != 4) ? ((PlacementStatus)5) : ((PlacementStatus)9))); __instance.m_placementStatus = placementStatus; Piece component = ((Component)val).GetComponent<Piece>(); if (component != null) { component.SetInvalidPlacementHeightlight(true); } } } private static bool Climber(Plant plant) { if (!(plant.m_attachDistance > 0f)) { return plant.m_growRadiusVines > 0f; } return true; } private static void Share(Plant plant) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected I4, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)plant).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (component.IsOwner()) { zDO.Set("RestlessClimb", (int)plant.m_status); return; } int num = zDO.GetInt("RestlessClimb", -1); if (num >= 0) { plant.m_status = (Status)num; } } } private static bool _till; private static bool _ground; private static bool _need; public static bool Free { get { if (PlantConfig.On) { return PlantConfig.GrowAnywhere.Value; } return false; } } public static void Relax(GameObject? ghost) { if (Free && !((Object)(object)ghost == (Object)null)) { Piece[] componentsInChildren = ghost.GetComponentsInChildren<Piece>(true); foreach (Piece obj in componentsInChildren) { obj.m_cultivatedGroundOnly = false; obj.m_groundOnly = false; obj.m_noInWater = false; } Plant[] componentsInChildren2 = ghost.GetComponentsInChildren<Plant>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].m_needCultivatedGround = false; } } } } [HarmonyPatch] internal static class PlantHarvest { [HarmonyPatch] private static class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Pickable), "Interact")] private static void AfterPick(Pickable __instance, Humanoid character, bool __result) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (__result && PlantConfig.On && !_busy && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && Ours(__instance)) { Piece val = SeedFor(__instance); if ((Object)(object)val != (Object)null) { Remember(val); } if (PlantConfig.BulkHarvest.Value) { Bulk(__instance, character); } if (PlantConfig.Replant.Value && __instance.m_respawnTimeMinutes <= 0f && (Object)(object)val != (Object)null) { Replant((Player?)(object)((character is Player) ? character : null), ((Component)__instance).transform.position, ((Component)__instance).transform.rotation, val); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Beehive), "Interact")] private static void AfterHive(Beehive __instance, Humanoid character, bool __result) { if (__result && PlantConfig.On && PlantConfig.BulkBeehives.Value && !_busy && !((Object)(object)character != (Object)(object)Player.m_localPlayer)) { BulkHives(__instance, character); } } [HarmonyPostfix] [HarmonyPatch(typeof(Plant), "Grow")] private static void StampGrown(Plant __instance, GameObject __result) { if ((Object)(object)__result == (Object)null) { return; } ZNetView component = __result.GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { Piece component2 = ((Component)__instance).GetComponent<Piece>(); long num = (((Object)(object)component2 != (Object)null) ? component2.GetCreator() : 0); if (num != 0L) { component.GetZDO().Set("RestlessPlanted", num); component.GetZDO().Set("RestlessReplant", Utils.GetPrefabName(((Component)__instance).gameObject)); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Beehive), "Awake")] private static void NameNest(Beehive __instance) { if (!Nest(__instance)) { return; } if (__instance.m_name == "$piece_beehive" || string.IsNullOrEmpty(__instance.m_name)) { __instance.m_name = "$piece_birdnest"; } if (__instance.m_extractText == "$piece_beehive_extract") { __instance.m_extractText = "$piece_birdnest_extract"; } if (__instance.m_checkText == "$piece_beehive_check") { __instance.m_checkText = "$piece_birdnest_check"; } if (__instance.m_areaText == "$piece_beehive_area") { __instance.m_areaText = "$piece_birdnest_area"; } if (__instance.m_freespaceText == "$piece_beehive_freespace") { __instance.m_freespaceText = "$piece_birdnest_freespace"; } if (__instance.m_sleepText == "$piece_beehive_sleep") { __instance.m_sleepText = "$piece_birdnest_sleep"; } if (__instance.m_happyText == "$piece_beehive_happy") { __instance.m_happyText = "$piece_birdnest_happy"; } string text = ((!((Object)(object)__instance.m_honeyItem != (Object)null)) ? null : __instance.m_honeyItem.m_itemData?.m_shared?.m_name); if (!(text != "$item_honey") || text == null) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("Feathers") : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { __instance.m_honeyItem = val2; } } } } private static Piece? _remembered; private static bool _busy; private static ZNetScene? _scene; private static float _nextCleanup; private static readonly Dictionary<string, Piece> Seeds = new Dictionary<string, Piece>(StringComparer.Ordinal); private const string SeedKey = "RestlessReplant"; private static readonly HashSet<string> CropNames = new HashSet<string>(StringComparer.Ordinal) { "Pickable_Carrot", "Pickable_SeedCarrot", "Pickable_Turnip", "Pickable_SeedTurnip", "Pickable_Onion", "Pickable_SeedOnion", "Pickable_Barley", "Pickable_Flax" }; private const string PlantedKey = "RestlessPlanted"; private static readonly Dictionary<ZDOID, ItemDrop> PickedDrops = new Dictionary<ZDOID, ItemDrop>(); private static ZDOID _picking; private static ItemDrop? _pickingDrop; private static readonly HashSet<int> Seen = new HashSet<int>(); internal static void Tick() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) if ((Object)(object)_scene != (Object)(object)ZNetScene.instance) { _scene = ZNetScene.instance; PickedDrops.Clear(); Seeds.Clear(); _remembered = null; } if (Time.unscaledTime < _nextCleanup) { return; } _nextCleanup = Time.unscaledTime + 2f; List<ZDOID> list = new List<ZDOID>(); foreach (KeyValuePair<ZDOID, ItemDrop> pickedDrop in PickedDrops) { if ((Object)(object)pickedDrop.Value == (Object)null || (Object)(object)pickedDrop.Value.m_nview == (Object)null || !pickedDrop.Value.m_nview.IsValid()) { list.Add(pickedDrop.Key); } } foreach (ZDOID item in list) { PickedDrops.Remove(item); } } private static Piece? SeedFor(Pickable crop) { string prefabName = Utils.GetPrefabName(((Component)crop).gameObject); string text = (((Object)(object)crop.m_nview != (Object)null && crop.m_nview.IsValid()) ? crop.m_nview.GetZDO().GetString("RestlessReplant", "") : ""); if (!string.IsNullOrEmpty(text)) { ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(text) : null); if ((Object)(object)val != (Object)null) { return val.GetComponent<Piece>(); } } if (Seeds.TryGetValue(prefabName, out Piece value)) { return value; } if ((Object)(object)ZNetScene.instance == (Object)null) { return null; } foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { Plant val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Plant>() : null); Piece val3 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || val2.m_grownPrefabs == null) { continue; } GameObject[] grownPrefabs = val2.m_grownPrefabs; foreach (GameObject val4 in grownPrefabs) { if ((Object)(object)val4 != (Object)null && Utils.GetPrefabName(val4) == prefabName) { Seeds[prefabName] = val3; return val3; } } } return null; } public static void Remember(Piece? piece) { if ((Object)(object)piece != (Object)null) { _remembered = piece; } } public static Piece? Hint() { if (!PlantConfig.Replant.Value) { return null; } return _remembered; } public static bool Grown(Pickable pickable) { return Ours(pickable); } private static bool Ours(Pickable pickable) { if ((Object)(object)pickable == (Object)null) { return false; } string prefabName = Utils.GetPrefabName(((Component)pickable).gameObject); if (prefabName.StartsWith("Restless_")) { return true; } if (CropNames.Contains(prefabName)) { return true; } Piece componentInParent = ((Component)pickable).GetComponentInParent<Piece>(); if ((Object)(object)componentInParent != (Object)null && componentInParent.GetCreator() != 0L) { return true; } ZNetView nview = pickable.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid()) { return nview.GetZDO().GetLong("RestlessPlanted", 0L) != 0; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "Pickup")] private static bool OneDrop(GameObject go, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) _picking = ZDOID.None; _pickingDrop = null; if (!PlantConfig.On) { return true; } ItemDrop val = (((Object)(object)go != (Object)null) ? go.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid()) { return true; } ZDOID uid = val.m_nview.GetZDO().m_uid; if (((ZDOID)(ref uid)).IsNone()) { return true; } if (PickedDrops.ContainsKey(uid)) { __result = false; return false; } _picking = uid; _pickingDrop = val; return true; } [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "Pickup")] private static void RememberDrop(bool __result) { //IL_0030: 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_0021: Unknown result type (might be due to invalid IL or missing references) if (__result && !((ZDOID)(ref _picking)).IsNone() && (Object)(object)_pickingDrop != (Object)null) { PickedDrops[_picking] = _pickingDrop; } _picking = ZDOID.None; _pickingDrop = null; } [HarmonyPrefix] [HarmonyPatch(typeof(Beehive), "RPC_Extract")] private static bool OneExtract(Beehive __instance) { ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (nview.IsOwner()) { return true; } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { nview.ClaimOwnership(); return true; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(Beehive), "GetTimeSinceLastUpdate")] private static void Clock(Beehive __instance) { ZNetView nview = __instance.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)ZNet.instance == (Object)null)) { ZDO zDO = nview.GetZDO(); if (zDO.GetLong(ZDOVars.s_lastTime, 0L) <= 1) { zDO.Set(ZDOVars.s_lastTime, ZNet.instance.GetTime().Ticks); } } } private static void BulkHives(Beehive picked, Humanoid character) { //IL_0016: 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_0022: Unknown result type (might be due to invalid IL or missing references) float range = ReachPolicy.HarvestReach(PlantConfig.HarvestRange.Value); Vector3 position = ((Component)picked).transform.position; _busy = true; try { foreach (Beehive item in Nearby<Beehive>(position, range)) { if (!((Object)(object)item == (Object)(object)picked) && SameHive(picked, item)) { item.Interact(character, false, false); } } } finally { _busy = false; } } private static void Bulk(Pickable picked, Humanoid character) { //IL_0016: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) float range = ReachPolicy.HarvestReach(PlantConfig.HarvestRange.Value); Vector3 position = ((Component)picked).transform.position; _busy = true; try { foreach (Pickable item in Nearby<Pickable>(position, range)) { if (!((Object)(object)item == (Object)(object)picked) && item.CanBePicked() && Ours(item)) { Vector3 position2 = ((Component)item).transform.position; Quaternion rotation = ((Component)item).transform.rotation; Piece val = SeedFor(item); bool flag = item.m_respawnTimeMinutes <= 0f; if (item.Interact(character, false, false) && PlantConfig.Replant.Value && flag && (Object)(object)val != (Object)null) { Replant((Player?)(object)((character is Player) ? character : null), position2, rotation, val); } } } } finally { _busy = false; } } private static IEnumerable<T> Nearby<T>(Vector3 origin, float range) where T : Component { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Seen.Clear(); Collider[] array = Physics.OverlapSphere(origin, range, -1, (QueryTriggerInteraction)2); Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)(object)val == (Object)null) { continue; } T componentInParent = ((Component)val).GetComponentInParent<T>(); if (!((Object)(object)componentInParent == (Object)null)) { Vector3 val2 = ((Component)componentInParent).transform.position - origin; if (!(((Vector3)(ref val2)).sqrMagnitude > range * range) && Seen.Add(((Object)(object)componentInParent).GetInstanceID())) { yield return componentInParent; } } } } private static void Replant(Player? player, Vector3 pos, Quaternion rot, Piece? piece) { //IL_0068: 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_004b: Unknown result type (might be due to invalid IL or missing references) Piece val = (((Object)(object)piece != (Object)null) ? piece : _remembered); if (!((Object)(object)player == (Object)null) && !((Object)(object)val == (Object)null) && player.HaveRequirements(val, (RequirementMode)0)) { if (!player.m_noPlacementCost && ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystem.instance.GetGlobalKey(val.FreeBuildKey()))) { player.ConsumeResources(val.m_resources, 0, -1, 1); } player.PlacePiece(val, pos, rot, false, false); } } private static bool Nest(Beehive hive) { if ((Object)(object)hive == (Object)null) { return false; } string obj = Utils.GetPrefabName(((Component)hive).gameObject) ?? ""; string text = hive.m_name ?? ""; if (obj.IndexOf("birdnest", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("birdnest", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool SameHive(Beehive a, Beehive b) { if (Nest(a) != Nest(b)) { return false; } return Utils.GetPrefabName(((Component)a).gameObject) == Utils.GetPrefabName(((Component)b).gameObject); } } internal static class PlantHover { [HarmonyPatch(typeof(Pickable), "GetHoverText")] private static class PickableHover { [HarmonyPostfix] private static void After(Pickable __instance, ref string __result) { if (!PlantConfig.On) { return; } if (PlantConfig.RegrowHint.Value && __instance.m_picked && __instance.m_respawnTimeMinutes > 0f) { double num = RemainingMinutes(__instance); if (num > 0.05) { string hoverName = __instance.GetHoverName(); __result = (string.IsNullOrEmpty(hoverName) ? ("Regrows in " + Format(num)) : (hoverName + "\nRegrows in " + Format(num))); } } if (!PlantConfig.Replant.Value || __instance.m_respawnTimeMinutes > 0f || !PlantHarvest.Grown(__instance)) { return; } Piece val = PlantHarvest.Hint(); if (!((Object)(object)val == (Object)null)) { string text = (string.IsNullOrEmpty(val.m_name) ? ((Object)val).name : Localization.instance.Localize(val.m_name)); if (string.IsNullOrEmpty(__result)) { __result = "Replant " + text; } else if (__result.IndexOf("Replant", StringComparison.OrdinalIgnoreCase) < 0) { __result = __result + "\nReplant " + text; } } } } [HarmonyPatch(typeof(Plant), "GetHoverText")] private static class SaplingHover { [HarmonyPostfix] private static void After(Plant __instance, ref string __result) { if (!PlantConfig.On || !PlantConfig.RegrowHint.Value) { return; } double num = ((double)__instance.GetGrowTime() - __instance.TimeSincePlanted()) / 60.0; if (!(num <= 0.05)) { string text = "Grows in " + Format(num); if (string.IsNullOrEmpty(__result)) { __result = text; } else if (__result.IndexOf("Grows in", StringComparison.OrdinalIgnoreCase) < 0) { __result = __result + "\n" + text; } } } } [HarmonyPatch(typeof(Pickable), "Awake")] private static class SproutWatch { [HarmonyPostfix] private static void After(Pickable __instance) { if (PlantConfig.On && Regrows(__instance)) { (((Component)__instance).GetComponent<PickSprout>() ?? ((Component)__instance).gameObject.AddComponent<PickSprout>()).Bind(__instance); } } } [HarmonyPatch(typeof(Pickable), "SetPicked")] private static class SproutPick { [HarmonyPostfix] private static void After(Pickable __instance) { ((Component)__instance).GetComponent<PickSprout>()?.Apply(); } } [HarmonyPatch(typeof(Pickable), "Interact")] private static class SproutHandsOff { [HarmonyPrefix] private static bool LeaveIt(Pickable __instance, ref bool __result) { if (!__instance.m_picked || (Object)(object)((Component)__instance).GetComponent<PickSprout>() == (Object)null) { return true; } __result = false; return false; } } internal static double RemainingMinutes(Pickable pick) { long num = PickedTime(pick); if (num <= 1) { return pick.m_respawnTimeMinutes; } if ((Object)(object)ZNet.instance == (Object)null) { return pick.m_respawnTimeMinutes; } double totalMinutes = (ZNet.instance.GetTime() - new DateTime(num)).TotalMinutes; return (double)pick.m_respawnTimeMinutes - totalMinutes; } private static long PickedTime(Pickable pick) { if ((Object)(object)pick.m_nview != (Object)null && pick.m_nview.IsValid()) { return pick.m_nview.GetZDO().GetLong(ZDOVars.s_pickedTime, 0L); } return pick.m_pickedTime; } private static bool Regrows(Pickable pick) { if (pick.m_respawnTimeMinutes <= 0f || (Object)(object)pick.m_hideWhenPicked == (Object)null) { return false; } return Utils.GetPrefabName(((Component)pick).gameObject).StartsWith("Restless_"); } private static string Format(double minutes) { if (minutes < 1.0) { return "soon"; } if (minutes < 60.0) { return $"{Mathf.CeilToInt((float)minutes)} min"; } int num = (int)(minutes / 60.0); int num2 = Mathf.CeilToInt((float)(minutes % 60.0)); if (num2 >= 60) { num++; num2 = 0; } if (num2 <= 0) { return $"{num}h"; } return $"{num}h {num2}m"; } } internal sealed class PickSprout : MonoBehaviour { private const float Tiny = 0.2f; private Pickable? _pick; private Transform? _visual; private Transform? _bush; private Vector3 _full = Vector3.one; private Vector3 _bushFull = Vector3.one; private float _next; public void Bind(Pickable pick) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) _pick = pick; Transform transform = pick.m_hideWhenPicked.transform; Transform val = FruitCluster(transform); if ((Object)(object)val != (Object)null) { _bush = transform; _bushFull = transform.localScale; _visual = val; } else { _bush = null; _visual = transform; } _full = _visual.localScale; Apply(); } private void LateUpdate() { if (!(Time.unscaledTime < _next)) { _next = Time.unscaledTime + 0.25f; Apply(); } } public void Apply() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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) if ((Object)(object)_pick == (Object)null || (Object)(object)_visual == (Object)null || _pick.m_respawnTimeMinutes <= 0f || _pick.m_enabled == 0) { return; } if ((Object)(object)_bush != (Object)null) { if (!((Component)_bush).gameObject.activeSelf) { ((Component)_bush).gameObject.SetActive(true); } _bush.localScale = _bushFull; } if (!_pick.m_picked) { _visual.localScale = _full; return; } if (!((Component)_visual).gameObject.activeSelf) { ((Component)_visual).gameObject.SetActive(true); } double num = PlantHover.RemainingMinutes(_pick); float num2 = Mathf.Clamp01(1f - (float)(num / (double)_pick.m_respawnTimeMinutes)); _visual.localScale = _full * Mathf.Lerp(0.2f, 1f, num2); } private static Transform? FruitCluster(Transform hidden) { Transform[] componentsInChildren = ((Component)hidden).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)(object)hidden) && IsFruit(((Object)val).name)) { return val; } } return null; } private static bool IsFruit(string name) { if (!name.Equals("Berrys", StringComparison.OrdinalIgnoreCase)) { return name.Equals("Berries", StringComparison.OrdinalIgnoreCase); } return true; } } internal static class PlantSettings { internal static IDisposable Register() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Expected O, but got Unknown //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Expected O, but got Unknown //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Expected O, but got Unknown //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Expected O, but got Unknown //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Expected O, but got Unknown //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Expected O, but got Unknown //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Expected O, but got Unknown //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Expected O, but got Unknown return SettingsPageApi.RegisterSettings("restless.plant", (SettingsSection[])(object)new SettingsSection[4] { new SettingsSection("Planting", (SettingsOption[])(object)new SettingsOption[5] { new SettingsOption("Enable RestlessPlant", (ConfigEntryBase)(object)PlantConfig.Enabled, true, "", true), new SettingsOption("Berry bushes and forage", (ConfigEntryBase)(object)PlantConfig.ExtraCrops, true, "", true), new SettingsOption("Extra saplings", (ConfigEntryBase)(object)PlantConfig.ExtraSaplings, true, "", true), new SettingsOption("Decorative plants", (ConfigEntryBase)(object)PlantConfig.ExtraFlora, true, "", true), new SettingsOption("Grow anywhere", (ConfigEntryBase)(object)PlantConfig.GrowAnywhere, true, "", true) }), new SettingsSection("Harvesting", (SettingsOption[])(object)new SettingsOption[4] { new SettingsOption("Harvest neighbouring crops", (ConfigEntryBase)(object)PlantConfig.BulkHarvest, true, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On), (Func<float>)null, (Func<string>)null), new SettingsOption("Collect neighbouring beehives", (ConfigEntryBase)(object)PlantConfig.BulkBeehives, true, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On), (Func<float>)null, (Func<string>)null), new SettingsOption("Harvest range", (ConfigEntryBase)(object)PlantConfig.HarvestRange, true, "m", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && (PlantConfig.BulkHarvest.Value || PlantConfig.BulkBeehives.Value) && !ReachPolicy.Global), (Func<float>)(() => ReachPolicy.HarvestReach(PlantConfig.HarvestRange.Value)), (Func<string>)(() => (PlantConfig.On && (PlantConfig.BulkHarvest.Value || PlantConfig.BulkBeehives.Value)) ? ((!ReachPolicy.Global) ? "Custom" : "Controlled by Global Reach") : "Feature disabled")), new SettingsOption("Replant on harvest", (ConfigEntryBase)(object)PlantConfig.Replant, true, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On), (Func<float>)null, (Func<string>)null) }), new SettingsSection("Your planting grid", (SettingsOption[])(object)new SettingsOption[6] { new SettingsOption("Grid planting", (ConfigEntryBase)(object)PlantConfig.Grid, false, "", false), new SettingsOption("Columns", (ConfigEntryBase)(object)PlantConfig.GridColumns, false, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && PlantConfig.Grid.Value), (Func<float>)null, (Func<string>)null), new SettingsOption("Rows", (ConfigEntryBase)(object)PlantConfig.GridRows, false, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && PlantConfig.Grid.Value), (Func<float>)null, (Func<string>)null), new SettingsOption("Minimum spacing", (ConfigEntryBase)(object)PlantConfig.Spacing, false, "m", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && PlantConfig.Grid.Value), (Func<float>)null, (Func<string>)null), new SettingsOption("Snap to existing field", (ConfigEntryBase)(object)PlantConfig.SnapToField, false, "", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && PlantConfig.Grid.Value), (Func<float>)null, (Func<string>)null), new SettingsOption("Snap range", (ConfigEntryBase)(object)PlantConfig.SnapRange, false, "m", false, (Func<bool>)null, (Func<bool>)(() => PlantConfig.On && PlantConfig.Grid.Value && PlantConfig.SnapToField.Value), (Func<float>)null, (Func<string>)null) }), new SettingsSection("Your controls and hints", (SettingsOption[])(object)new SettingsOption[6] { new SettingsOption("Show regrowth time", (ConfigEntryBase)(object)PlantConfig.RegrowHint, false, "", false), new SettingsOption("Add column", (ConfigEntryBase)(object)PlantConfig.ColsUp, false, "", false), new SettingsOption("Remove column", (ConfigEntryBase)(object)PlantConfig.ColsDown, false, "", false), new SettingsOption("Add row", (ConfigEntryBase)(object)PlantConfig.RowsUp, false, "", false), new SettingsOption("Remove row", (ConfigEntryBase)(object)PlantConfig.RowsDown, false, "", false), new SettingsOption("Toggle field snapping", (ConfigEntryBase)(object)PlantConfig.SnapToggle, false, "", false) }) }); } } [BepInPlugin("restless.plant", "RestlessPlant", "0.2.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("restless.core", "0.3.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "restless.plant"; public const string PluginName = "RestlessPlant"; public const string PluginVersion = "0.2.4"; private Harmony? _harmony; private IDisposable? _settings; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PlantConfig.Bind(((BaseUnityPlugin)this).Config); _settings = PlantSettings.Register(); CropPieces.Load(); _harmony = new Harmony("restless.plant"); _harmony.PatchAll(); Log.LogInfo((object)"RestlessPlant 0.2.4 loaded."); } private void Update() { PlantHarvest.Tick(); if (!Console.IsVisible()) { PlantGrid.Tick(); } } private void OnDestroy() { _settings?.Dispose(); PlantGrid.Clear(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } }