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 Lootheim v1.0.2
BepInEx/plugins/Lootheim/Lootheim.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace Lootheim; [BepInPlugin("Lootheim.Valheim", "Lootheim", "1.5.4")] public sealed class LootheimPlugin : BaseUnityPlugin { internal sealed class CropInfo { internal string SaplingPrefab; internal string ResourcePrefab; internal CropInfo(string saplingPrefab, string resourcePrefab) { SaplingPrefab = saplingPrefab; ResourcePrefab = resourcePrefab; } } [HarmonyPatch(typeof(Container), "Awake")] private static class ContainerRegistryPatch { private static void Postfix(Container __instance) { if ((Object)(object)__instance != (Object)null) { KnownContainers.Add(__instance); } } } [HarmonyPatch] private static class GridPlantBlockVanillaPlacementPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (methods[i].Name == "TryPlacePiece") { yield return methods[i]; } } } private static bool Prefix(Player __instance) { //IL_0057: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || Enabled == null || !Enabled.Value || FarmAssistEnabled == null || !FarmAssistEnabled.Value || GridPlantHotkey == null) { return true; } KeyboardShortcut value = GridPlantHotkey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if ((int)mainKey == 0 || !Input.GetKey(mainKey)) { return true; } GameObject placementGhost = GetPlacementGhost(__instance); if ((Object)(object)placementGhost == (Object)null) { return true; } string b = NormalizePrefabName(((Object)placementGhost).name); foreach (KeyValuePair<string, CropInfo> farmCrop in FarmCrops) { if (string.Equals(NormalizePrefabName(farmCrop.Value.SaplingPrefab), b, StringComparison.OrdinalIgnoreCase)) { return false; } } return true; } } [HarmonyPatch] private static class PickableInteractHardGuardPatch { private static MethodBase TargetMethod() { return _pickableInteractMethod; } private static bool Prefix(Pickable __instance) { if ((Object)(object)__instance == (Object)null) { return true; } if (!CallOriginatesFromLootheim()) { return true; } if (Enabled == null || !Enabled.Value) { return false; } if (CallOriginatesFromFarmAssist()) { return true; } if (AutoHarvestEnabled == null || !AutoHarvestEnabled.Value) { return false; } string key = NormalizePrefabName(((Object)((Component)__instance).gameObject).name); if (!PickableToggles.TryGetValue(key, out var value)) { return false; } return value?.Value ?? false; } } [HarmonyPatch] private static class PickableInteractMultiplierPatch { private sealed class State { internal Pickable Pickable; internal int Original; internal bool Changed; } private static MethodBase TargetMethod() { return _pickableInteractMethod; } private static void Prefix(Pickable __instance, ref State __state) { __state = null; int resourceMultiplier = GetResourceMultiplier(); if (resourceMultiplier <= 1 || (Object)(object)__instance == (Object)null || _pickableAmountField == null) { return; } try { int num = Convert.ToInt32(_pickableAmountField.GetValue(__instance)); __state = new State(); __state.Pickable = __instance; __state.Original = num; __state.Changed = true; _pickableAmountField.SetValue(__instance, Mathf.Max(1, num) * resourceMultiplier); } catch { __state = null; } } private static Exception Finalizer(Pickable __instance, State __state, Exception __exception) { if (__state != null && __state.Changed && (Object)(object)__state.Pickable != (Object)null && _pickableAmountField != null) { try { _pickableAmountField.SetValue(__state.Pickable, __state.Original); } catch { } } return __exception; } } [HarmonyPatch] private static class DropTableMultiplierPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(DropTable).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo m in methods) { if ((!(m.Name != "GetDropList") || !(m.Name != "GetDrops") || !(m.Name != "GenerateDropList")) && typeof(IList).IsAssignableFrom(m.ReturnType)) { yield return m; } } } private static void Postfix(object __result) { int resourceMultiplier = GetResourceMultiplier(); if (resourceMultiplier <= 1 || _multiplierGuard || __result == null || !IsResourceHarvestDropCall() || !(__result is IList { IsFixedSize: false, IsReadOnly: false } list)) { return; } try { _multiplierGuard = true; int count = list.Count; for (int i = 1; i < resourceMultiplier; i++) { for (int j = 0; j < count; j++) { list.Add(list[j]); } } } catch { } finally { _multiplierGuard = false; } } } [HarmonyPatch] private static class CharacterDropMultiplierPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(CharacterDrop).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo m in methods) { if ((!(m.Name != "GenerateDropList") || !(m.Name != "GetDropList") || !(m.Name != "GetDrops")) && typeof(IList).IsAssignableFrom(m.ReturnType)) { yield return m; } } } private static void Postfix(object __result) { int resourceMultiplier = GetResourceMultiplier(); if (resourceMultiplier <= 1 || _multiplierGuard || __result == null || !(__result is IList { IsFixedSize: false, IsReadOnly: false } list)) { return; } try { _multiplierGuard = true; int count = list.Count; for (int i = 1; i < resourceMultiplier; i++) { for (int j = 0; j < count; j++) { list.Add(list[j]); } } } catch { } finally { _multiplierGuard = false; } } } internal static LootheimPlugin Instance; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> AutoHarvestEnabled; internal static ConfigEntry<float> AutoHarvestRadius; internal static ConfigEntry<float> PickupRadius; internal static ConfigEntry<bool> ResourceMultiplierEnabled; internal static ConfigEntry<int> ResourceMultiplier; internal static ConfigEntry<bool> MiningAuraEnabled; internal static ConfigEntry<float> MiningAuraRadius; public static ConfigEntry<KeyboardShortcut> MassActionHotkey; public static ConfigEntry<KeyboardShortcut> ControllerPickupHotkey; public static ConfigEntry<float> MassInteractRange; public static ConfigEntry<int> PlantGridWidth; public static ConfigEntry<int> PlantGridLength; public static ConfigEntry<bool> IgnoreStamina; public static ConfigEntry<bool> IgnoreDurability; public static ConfigEntry<bool> GridAnchorWidth; public static ConfigEntry<bool> GridAnchorLength; public static ConfigEntry<float> NonPlantFloraSpacing; internal static ConfigEntry<bool> FarmAssistEnabled; internal static ConfigEntry<KeyboardShortcut> FarmAssistHotkey; internal static ConfigEntry<float> FarmAssistRadius; internal static ConfigEntry<bool> AutoReplant; internal static ConfigEntry<KeyboardShortcut> GridPlantHotkey; internal static ConfigEntry<int> GridPlantLength; internal static ConfigEntry<int> GridPlantWidth; internal static ConfigEntry<float> GridPlantSpacing; internal static ConfigEntry<float> FarmAssistChestRange; private static readonly HashSet<Container> KnownContainers = new HashSet<Container>(); private static readonly List<Container> CachedNearbyContainers = new List<Container>(); private static float _nextContainerRefresh; private static Vector3 _lastContainerRefreshPosition; private readonly List<GameObject> _gridPreviewGhosts = new List<GameObject>(); private readonly List<bool> _gridPreviewValid = new List<bool>(); private bool _gridPreviewActive; private string _gridPreviewSaplingPrefab; private string _gridPreviewResourcePrefab; internal static readonly Dictionary<string, ConfigEntry<bool>> PickableToggles = new Dictionary<string, ConfigEntry<bool>>(StringComparer.OrdinalIgnoreCase); private Harmony _harmony; private float _nextHarvestScan; private float _nextMiningAuraScan; private float _nextFarmAssistAllowed; private Player _trackedPlayer; private bool _hasOriginalPickupRange; private float _originalPickupRange; private static FieldInfo _pickablePickedField; private static FieldInfo _pickableAmountField; private static FieldInfo _playerAutoPickupRangeField; private static MethodInfo _pickableInteractMethod; [ThreadStatic] private static bool _multiplierGuard; private static readonly HashSet<Pickable> SeenPickables = new HashSet<Pickable>(); private static readonly string[] VanillaPickables = new string[84] { "BlueberryBush", "CloudberryBush", "goblin_totempole", "hanging_hairstrands", "LingonberryBush", "LuredFaderEmber", "LuredWisp", "Morkhalla_Eye1", "Morkhalla_Eye2", "Morkhalla_Eye3", "Morkhalla_Eye4", "Morkhalla_Eye5_gemstone", "Morkhalla_Eye6_gemstone", "Morkhalla_Eye7_gemstone", "Pickable_Ashstone", "Pickable_Barley", "Pickable_Barley_Wild", "Pickable_BlackCoreStand", "Pickable_BogIronOre", "Pickable_Branch", "Pickable_Branch_Snow", "Pickable_Carrot", "Pickable_Charredskull", "Pickable_Dandelion", "Pickable_DragonEgg", "Pickable_DvergerThing", "Pickable_DvergrLantern", "Pickable_DvergrMineTreasure", "Pickable_DvergrStein", "Pickable_Fiddlehead", "Pickable_Fishingrod", "Pickable_Flax", "Pickable_Flax_Wild", "Pickable_Flint", "Pickable_ForestCryptRemains01", "Pickable_ForestCryptRemains02", "Pickable_ForestCryptRemains03", "Pickable_ForestCryptRemains04", "Pickable_FrostCoreHanger", "Pickable_GlowWorm", "Pickable_Hairstrands01", "Pickable_Hairstrands02", "Pickable_HardRockOffspring", "Pickable_Kale", "Pickable_MeatPile", "Pickable_Meteorite", "Pickable_MoltenCoreStand", "Pickable_MountainCaveCrystal", "Pickable_MountainCaveObsidian", "Pickable_MountainRemains01_buried", "Pickable_Mushroom", "Pickable_Mushroom_blue", "Pickable_Mushroom_JotunPuffs", "Pickable_Mushroom_Magecap", "Pickable_Mushroom_yellow", "Pickable_Oat", "Pickable_Obsidian", "Pickable_Onion", "Pickable_Pot_Shard", "Pickable_Poteitr", "Pickable_RoyalJelly", "Pickable_SeedCarrot", "Pickable_SeedKale", "Pickable_SeedOnion", "Pickable_SeedTurnip", "Pickable_SmokePuff", "Pickable_Snowball", "Pickable_Stone", "Pickable_StoneRock", "Pickable_SulfurRock", "Pickable_SurtlingCoreStand", "Pickable_Swordpiece1", "Pickable_Swordpiece2", "Pickable_Swordpiece3", "Pickable_Tar", "Pickable_TarBig", "Pickable_Thistle", "Pickable_Tin", "Pickable_Turnip", "Pickable_VoltureEgg", "Placeable_Stone", "RaspberryBush", "VineAsh", "VineGreen" }; internal static readonly Dictionary<string, CropInfo> FarmCrops = new Dictionary<string, CropInfo>(StringComparer.OrdinalIgnoreCase) { { "Pickable_Carrot", new CropInfo("sapling_carrot", "CarrotSeeds") }, { "Pickable_Turnip", new CropInfo("sapling_turnip", "TurnipSeeds") }, { "Pickable_Onion", new CropInfo("sapling_onion", "OnionSeeds") }, { "Pickable_Barley", new CropInfo("sapling_barley", "Barley") }, { "Pickable_Flax", new CropInfo("sapling_flax", "Flax") }, { "Pickable_Kale", new CropInfo("sapling_Kale", "KaleSeeds") }, { "Pickable_Oat", new CropInfo("sapling_oat", "OatSeeds") } }; private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Expected O, but got Unknown //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Expected O, but got Unknown Instance = this; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for Lootheim."); AutoHarvestEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto Harvest", "Enabled", true, "Automatically harvest enabled vanilla Pickables inside the configured radius."); AutoHarvestRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Auto Harvest", "Harvest Radius (m)", 6f, new ConfigDescription("How far from the player enabled Pickables can be automatically harvested.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 50f), new object[0])); PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Pickup Magnet", "Pickup Radius (m)", 10f, new ConfigDescription("How far Valheim's normal auto-pickup magnet can pull dropped items toward you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), new object[0])); ResourceMultiplierEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Resource Multiplier", "Enabled", true, "Enable multiplied drops from Pickables, crops, trees/logs, rocks/ore, monsters and animals."); ResourceMultiplier = ((BaseUnityPlugin)this).Config.Bind<int>("Resource Multiplier", "Multiplier", 1, new ConfigDescription("Resource harvest multiplier. Uses whole-number multipliers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[0])); MiningAuraEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining Aura", "Enabled", false, "While a pickaxe is equipped, hold Shift to instantly mine nearby resource nodes."); MiningAuraRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Mining Aura", "Mining Radius (m)", 8f, new ConfigDescription("Radius around the character affected by Mining Aura.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), new object[0])); MassActionHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Farm Assist - Hotkeys", "MassActionHotkey", new KeyboardShortcut((KeyCode)304, (KeyCode[])(object)new KeyCode[0]), "Mass activation hotkey for multi-pickup/multi-plant."); ControllerPickupHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Farm Assist - Hotkeys", "ControllerPickupHotkey", new KeyboardShortcut((KeyCode)334, (KeyCode[])(object)new KeyCode[0]), "Mass activation hotkey for multi-pickup/multi-plant for controller."); MassInteractRange = ((BaseUnityPlugin)this).Config.Bind<float>("Farm Assist - Pickup", "MassInteractRange", 5f, "Range of mass pickup."); AutoReplant = ((BaseUnityPlugin)this).Config.Bind<bool>("Farm Assist - Pickup", "Auto Replant", true, "When using the mass harvest hotkey on farm crops, immediately replant each harvested crop in the same position if the required seed/crop is available in inventory or nearby chests."); FarmAssistChestRange = ((BaseUnityPlugin)this).Config.Bind<float>("Farm Assist - Pickup", "Replant Chest Range", 20f, new ConfigDescription("How far Farm Assist can pull seeds/crops from nearby chests for auto replant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[0])); PlantGridWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Farm Assist - PlantGrid", "PlantGridWidth", 5, "Grid width of auto-plant. Recommend odd-number; default is 5."); PlantGridLength = ((BaseUnityPlugin)this).Config.Bind<int>("Farm Assist - PlantGrid", "PlantGridLength", 5, "Grid length of auto-plant. Recommend odd-number; default is 5."); IgnoreStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Farm Assist - Plant", "IgnoreStamina", false, "Ignore stamina requirements when planting extra rows."); IgnoreDurability = ((BaseUnityPlugin)this).Config.Bind<bool>("Farm Assist - Plant", "IgnoreDurability", false, "Ignore cultivator durability when planting extra rows."); GridAnchorWidth = ((BaseUnityPlugin)this).Config.Bind<bool>("Farm Assist - PlantGrid", "GridAnchorWidth", true, "Planting grid anchor point (width). Enabled extends left/right from crosshair; disable to anchor at the side."); GridAnchorLength = ((BaseUnityPlugin)this).Config.Bind<bool>("Farm Assist - PlantGrid", "GridAnchorLength", true, "Planting grid anchor point (length). Enabled extends forward/backward from crosshair; disable to anchor at the side."); NonPlantFloraSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Farm Assist - PlantGrid", "NonPlantFloraSpacing", 1f, new ConfigDescription("Grid spacing used for Plant Everything flora that do not have Valheim's Plant component.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), new object[0])); for (int i = 0; i < VanillaPickables.Length; i++) { string text = VanillaPickables[i]; PickableToggles[text] = ((BaseUnityPlugin)this).Config.Bind<bool>("Pickables", text, true, "Allow Lootheim to auto-harvest this vanilla Pickable. OFF is a hard block."); } CacheMembers(); _harmony = new Harmony("Lootheim.Valheim"); _harmony.PatchAll(typeof(LootheimPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Lootheim v1.5.4 loaded. Farm Assist mass harvest auto-replant is enabled."); } private void OnDestroy() { ClearGridPreview(); RestorePickupRadius(); if (_harmony != null) { _harmony.UnpatchSelf(); } Instance = null; } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { RestorePickupRadius(); return; } if (!Enabled.Value) { RestorePickupRadius(); return; } ApplyPickupRadius(localPlayer); if (AutoHarvestEnabled.Value && Time.time >= _nextHarvestScan) { _nextHarvestScan = Time.time + 0.2f; RunAutoHarvest(localPlayer, Mathf.Clamp(AutoHarvestRadius.Value, 0.5f, 50f)); } if (MiningAuraEnabled.Value && Time.time >= _nextMiningAuraScan) { _nextMiningAuraScan = Time.time + 0.15f; if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) { HandleMiningAura(localPlayer, Mathf.Clamp(MiningAuraRadius.Value, 1f, 30f)); } } } private static void CacheMembers() { _pickablePickedField = AccessTools.Field(typeof(Pickable), "m_picked"); _pickableAmountField = AccessTools.Field(typeof(Pickable), "m_amount"); _playerAutoPickupRangeField = AccessTools.Field(typeof(Player), "m_autoPickupRange"); MethodInfo[] methods = typeof(Pickable).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (!(methods[i].Name != "Interact")) { ParameterInfo[] parameters = methods[i].GetParameters(); if (parameters.Length > 0 && typeof(Humanoid).IsAssignableFrom(parameters[0].ParameterType)) { _pickableInteractMethod = methods[i]; break; } } } } private static bool IsPickableEnabled(string prefab) { if (string.IsNullOrEmpty(prefab)) { return false; } if (!PickableToggles.TryGetValue(prefab, out var value)) { return false; } return value?.Value ?? false; } private static void RunAutoHarvest(Player player, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Collider[] array; try { array = Physics.OverlapSphere(((Component)player).transform.position, radius, -1, (QueryTriggerInteraction)2); } catch { return; } SeenPickables.Clear(); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Pickable val2 = null; try { val2 = ((Component)val).GetComponentInParent<Pickable>(); } catch { } if (!((Object)(object)val2 == (Object)null) && !SeenPickables.Contains(val2)) { SeenPickables.Add(val2); string prefab = NormalizePrefabName(((Object)((Component)val2).gameObject).name); if (IsPickableEnabled(prefab) && !IsAlreadyPicked(val2)) { TryInteractWithPickable(val2, player); } } } } internal static bool IsAlreadyPicked(Pickable pickable) { if ((Object)(object)pickable == (Object)null || _pickablePickedField == null) { return false; } try { return Convert.ToBoolean(_pickablePickedField.GetValue(pickable)); } catch { return false; } } private static bool TryInteractWithPickable(Pickable pickable, Player player) { if ((Object)(object)pickable == (Object)null || (Object)(object)player == (Object)null || _pickableInteractMethod == null) { return false; } try { ParameterInfo[] parameters = _pickableInteractMethod.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; if (typeof(Humanoid).IsAssignableFrom(parameterType)) { array[i] = player; } else if (parameterType == typeof(bool)) { array[i] = false; } else if (parameterType == typeof(int)) { array[i] = 0; } else if (parameterType == typeof(float)) { array[i] = 0f; } else { array[i] = null; } } if (!(_pickableInteractMethod.Invoke(pickable, array) is bool result)) { return true; } return result; } catch { return false; } } private static void ApplyPickupRadius(Player player) { if ((Object)(object)player == (Object)null || _playerAutoPickupRangeField == null) { return; } try { if ((Object)(object)Instance._trackedPlayer != (Object)(object)player) { Instance.RestorePickupRadius(); Instance._trackedPlayer = player; } if (!Instance._hasOriginalPickupRange) { Instance._originalPickupRange = Convert.ToSingle(_playerAutoPickupRangeField.GetValue(player)); Instance._hasOriginalPickupRange = true; } _playerAutoPickupRangeField.SetValue(player, Mathf.Clamp(PickupRadius.Value, 2f, 50f)); } catch { } } private void RestorePickupRadius() { if (!_hasOriginalPickupRange || (Object)(object)_trackedPlayer == (Object)null || _playerAutoPickupRangeField == null) { _trackedPlayer = null; _hasOriginalPickupRange = false; return; } try { _playerAutoPickupRangeField.SetValue(_trackedPlayer, _originalPickupRange); } catch { } _trackedPlayer = null; _hasOriginalPickupRange = false; } private static int GetResourceMultiplier() { if (Enabled == null || ResourceMultiplierEnabled == null || ResourceMultiplier == null || !Enabled.Value || !ResourceMultiplierEnabled.Value) { return 1; } return Mathf.Clamp(ResourceMultiplier.Value, 1, 20); } private static bool CallOriginatesFromLootheim() { try { StackTrace stackTrace = new StackTrace(); StackFrame[] frames = stackTrace.GetFrames(); if (frames == null) { return false; } for (int i = 0; i < frames.Length; i++) { MethodBase method = frames[i].GetMethod(); if (!(method == null)) { string name = method.Name; Type declaringType = method.DeclaringType; string text = ((declaringType == null) ? "" : declaringType.FullName); if (string.Equals(name, "RunAutoHarvest", StringComparison.Ordinal) || string.Equals(name, "RunFarmAssist", StringComparison.Ordinal)) { return true; } if (!string.IsNullOrEmpty(text) && (text.StartsWith("LootheimStaticHarvest.", StringComparison.OrdinalIgnoreCase) || text.IndexOf("Lootheim.StaticHarvest", StringComparison.OrdinalIgnoreCase) >= 0)) { return true; } } } } catch { } return false; } private static bool CallOriginatesFromFarmAssist() { try { StackTrace stackTrace = new StackTrace(); StackFrame[] frames = stackTrace.GetFrames(); if (frames == null) { return false; } for (int i = 0; i < frames.Length; i++) { MethodBase method = frames[i].GetMethod(); if (!(method == null) && (string.Equals(method.Name, "RunFarmAssist", StringComparison.Ordinal) || string.Equals(method.Name, "RunGridPlant", StringComparison.Ordinal))) { return true; } } } catch { } return false; } private static bool IsResourceHarvestDropCall() { try { StackTrace stackTrace = new StackTrace(); StackFrame[] frames = stackTrace.GetFrames(); if (frames == null) { return false; } for (int i = 0; i < frames.Length; i++) { MethodBase method = frames[i].GetMethod(); if (!(method == null) && !(method.DeclaringType == null)) { string fullName = method.DeclaringType.FullName; if (!string.IsNullOrEmpty(fullName) && (fullName.IndexOf("TreeBase", StringComparison.OrdinalIgnoreCase) >= 0 || fullName.IndexOf("TreeLog", StringComparison.OrdinalIgnoreCase) >= 0 || fullName.IndexOf("MineRock", StringComparison.OrdinalIgnoreCase) >= 0 || fullName.IndexOf("Destructible", StringComparison.OrdinalIgnoreCase) >= 0 || fullName.IndexOf("Beehive", StringComparison.OrdinalIgnoreCase) >= 0 || fullName.IndexOf("SapCollector", StringComparison.OrdinalIgnoreCase) >= 0)) { return true; } } } } catch { } return false; } private static void HandleMiningAura(Player player, float radius) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !IsPickaxeEquipped(player)) { return; } Collider[] array; try { array = Physics.OverlapSphere(((Component)player).transform.position, radius, -1, (QueryTriggerInteraction)2); } catch { return; } HashSet<Component> hashSet = new HashSet<Component>(); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Component val2 = null; try { val2 = (Component)(object)((Component)val).GetComponentInParent<MineRock5>(); if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)((Component)val).GetComponentInParent<MineRock>(); } if ((Object)(object)val2 == (Object)null) { val2 = (Component)(object)((Component)val).GetComponentInParent<Destructible>(); } } catch { } if (!((Object)(object)val2 == (Object)null) && !hashSet.Contains(val2)) { hashSet.Add(val2); if (!(val2 is Destructible) || IsResourceDestructible((Destructible)(object)((val2 is Destructible) ? val2 : null))) { TryOneShotMine(player, val2, val); } } } } private static bool IsPickaxeEquipped(Player player) { if ((Object)(object)player == (Object)null) { return false; } try { ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon == null || currentWeapon.m_shared == null) { return false; } if (currentWeapon.m_shared.m_damages.m_pickaxe > 0f) { return true; } string name = currentWeapon.m_shared.m_name; return !string.IsNullOrEmpty(name) && name.IndexOf("pickaxe", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return false; } } private static bool IsResourceDestructible(Destructible destructible) { if ((Object)(object)destructible == (Object)null) { return false; } string text = NormalizePrefabName(((Object)((Component)destructible).gameObject).name); string text2 = text.ToLowerInvariant(); if (!text2.Contains("rock") && !text2.Contains("stone") && !text2.Contains("copper") && !text2.Contains("silver") && !text2.Contains("obsidian") && !text2.Contains("iron") && !text2.Contains("flametal") && !text2.Contains("marble") && !text2.Contains("meteor") && !text2.Contains("deposit")) { return text2.Contains("mine"); } return true; } private static void TryOneShotMine(Player player, Component target, Collider collider) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0069: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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) if ((Object)(object)player == (Object)null || (Object)(object)target == (Object)null) { return; } try { HitData val = new HitData(); val.m_damage.m_pickaxe = 1000000f; val.m_toolTier = 99; Vector3 point; if (!((Object)(object)collider != (Object)null)) { point = target.transform.position; } else { Bounds bounds = collider.bounds; point = ((Bounds)(ref bounds)).center; } val.m_point = point; val.m_hitCollider = collider; Vector3 dir = target.transform.position - ((Component)player).transform.position; if (((Vector3)(ref dir)).sqrMagnitude > 0.001f) { ((Vector3)(ref dir)).Normalize(); } val.m_dir = dir; val.SetAttacker((Character)(object)player); MethodInfo[] methods = ((object)target).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Damage")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(HitData)) { methodInfo.Invoke(target, new object[1] { val }); break; } } } } catch { } } private static void RunFarmAssist(Player player, float radius) { //IL_0006: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) Collider[] array; try { array = Physics.OverlapSphere(((Component)player).transform.position, radius, -1, (QueryTriggerInteraction)2); } catch { return; } HashSet<Pickable> hashSet = new HashSet<Pickable>(); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Pickable val2 = null; try { val2 = ((Component)val).GetComponentInParent<Pickable>(); } catch { } if (!((Object)(object)val2 == (Object)null) && !hashSet.Contains(val2)) { string key = NormalizePrefabName(((Object)((Component)val2).gameObject).name); if (FarmCrops.ContainsKey(key) && !IsAlreadyPicked(val2)) { hashSet.Add(val2); } } } int num = 0; int num2 = 0; foreach (Pickable item in hashSet) { if ((Object)(object)item == (Object)null) { continue; } string key2 = NormalizePrefabName(((Object)((Component)item).gameObject).name); if (!FarmCrops.TryGetValue(key2, out var value)) { continue; } Vector3 position = ((Component)item).transform.position; Quaternion rotation = ((Component)item).transform.rotation; if (!TryInteractWithPickable(item, player)) { continue; } num++; if (AutoReplant.Value && ConsumeOneResource(player, value.ResourcePrefab)) { if (SpawnSapling(value.SaplingPrefab, position, rotation)) { num2++; } else { RefundOneResource(player, value.ResourcePrefab); } } } if (num > 0) { ShowCenterMessage("Farm Assist: harvested " + num + (AutoReplant.Value ? (", replanted " + num2) : "")); } } private static bool IsFarmAssistPressedThisFrame() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (FarmAssistHotkey == null) { return false; } KeyboardShortcut value = FarmAssistHotkey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if ((int)mainKey == 0) { return false; } if (!Input.GetKeyDown(mainKey)) { return false; } IEnumerable<KeyCode> modifiers = ((KeyboardShortcut)(ref value)).Modifiers; if (modifiers != null) { foreach (KeyCode item in modifiers) { if (!Input.GetKey(item)) { return false; } } } return true; } private void HandleGridPreviewAndPlacement(Player player) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !FarmAssistEnabled.Value) { ClearGridPreview(); return; } KeyboardShortcut value = GridPlantHotkey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; if ((int)mainKey == 0 || !Input.GetKey(mainKey)) { ClearGridPreview(); return; } GameObject placementGhost = GetPlacementGhost(player); if ((Object)(object)placementGhost == (Object)null) { ClearGridPreview(); return; } string b = NormalizePrefabName(((Object)placementGhost).name); CropInfo cropInfo = null; foreach (KeyValuePair<string, CropInfo> farmCrop in FarmCrops) { if (string.Equals(NormalizePrefabName(farmCrop.Value.SaplingPrefab), b, StringComparison.OrdinalIgnoreCase)) { cropInfo = farmCrop.Value; break; } } if (cropInfo == null) { ClearGridPreview(); return; } _gridPreviewActive = true; _gridPreviewSaplingPrefab = cropInfo.SaplingPrefab; _gridPreviewResourcePrefab = cropInfo.ResourcePrefab; UpdateGridPreview(player, placementGhost, Mathf.Clamp(GridPlantLength.Value, 1, 30), Mathf.Clamp(GridPlantWidth.Value, 1, 30), Mathf.Clamp(GridPlantSpacing.Value, 1.1f, 4f)); if (Input.GetMouseButtonDown(0)) { PlaceCurrentGrid(player, placementGhost, cropInfo, Mathf.Clamp(GridPlantLength.Value, 1, 30), Mathf.Clamp(GridPlantWidth.Value, 1, 30), Mathf.Clamp(GridPlantSpacing.Value, 1.1f, 4f)); } } private void UpdateGridPreview(Player player, GameObject placementGhost, int length, int width, float spacing) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0153: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)placementGhost == (Object)null) { return; } int num = length * width; while (_gridPreviewGhosts.Count < num) { GameObject val = null; try { val = Object.Instantiate<GameObject>(placementGhost); ((Object)val).name = "LootheimGridPreview"; DisablePreviewBehaviours(val); } catch { } _gridPreviewGhosts.Add(val); _gridPreviewValid.Add(item: false); } while (_gridPreviewGhosts.Count > num) { int num2 = _gridPreviewGhosts.Count - 1; GameObject val2 = _gridPreviewGhosts[num2]; if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } _gridPreviewGhosts.RemoveAt(num2); if (_gridPreviewValid.Count > num2) { _gridPreviewValid.RemoveAt(num2); } } while (_gridPreviewValid.Count < num) { _gridPreviewValid.Add(item: false); } Vector3 position = placementGhost.transform.position; Quaternion rotation = placementGhost.transform.rotation; Vector3 val3 = Vector3.ProjectOnPlane(placementGhost.transform.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val3)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f) { Vector3 val4 = Vector3.ProjectOnPlane(((Component)player).transform.forward, Vector3.up); normalized = ((Vector3)(ref val4)).normalized; } Vector3 val5 = Vector3.Cross(Vector3.up, normalized); Vector3 normalized2 = ((Vector3)(ref val5)).normalized; int num3 = 0; for (int i = 0; i < length; i++) { for (int j = 0; j < width; j++) { GameObject val6 = _gridPreviewGhosts[num3]; Vector3 position2 = position + normalized * ((float)i * spacing) + normalized2 * ((float)j * spacing); position2 = SnapPlantToGround(position2); bool flag = IsPlantPositionClear(player, position2, Mathf.Min(0.55f, spacing * 0.35f)); _gridPreviewValid[num3] = flag; if ((Object)(object)val6 != (Object)null) { val6.transform.position = position2; val6.transform.rotation = rotation; SetPreviewValidityVisual(val6, flag); if (!val6.activeSelf) { val6.SetActive(true); } } num3++; } } } private static void DisablePreviewBehaviours(GameObject preview) { if ((Object)(object)preview == (Object)null) { return; } try { Collider[] componentsInChildren = preview.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } } catch { } try { MonoBehaviour[] componentsInChildren2 = preview.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren2) { if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = false; } } } catch { } } private static bool IsPlantPositionClear(Player player, Vector3 position, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_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) try { Collider[] array = Physics.OverlapSphere(position + Vector3.up * 0.35f, Mathf.Max(0.25f, radius), -1, (QueryTriggerInteraction)1); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } Heightmap componentInParent = ((Component)val).GetComponentInParent<Heightmap>(); if ((Object)(object)componentInParent != (Object)null || ((Object)(object)player != (Object)null && ((Component)val).transform.IsChildOf(((Component)player).transform))) { continue; } Transform val2 = ((Component)val).transform; bool flag = false; while ((Object)(object)val2 != (Object)null) { if ((Object)(object)((Component)val2).gameObject != (Object)null && ((Object)((Component)val2).gameObject).name == "LootheimGridPreview") { flag = true; break; } val2 = val2.parent; } if (!flag) { return false; } } } catch { return false; } return true; } private static void SetPreviewValidityVisual(GameObject preview, bool valid) { //IL_006c: 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) if ((Object)(object)preview == (Object)null) { return; } try { Renderer[] componentsInChildren = preview.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material material = val.material; if (!((Object)(object)material == (Object)null)) { if (valid) { material.color = new Color(0.35f, 1f, 0.35f, 0.55f); } else { material.color = new Color(1f, 0.15f, 0.15f, 0.65f); } } } } catch { } } private void ClearGridPreview() { for (int i = 0; i < _gridPreviewGhosts.Count; i++) { GameObject val = _gridPreviewGhosts[i]; if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _gridPreviewGhosts.Clear(); _gridPreviewValid.Clear(); _gridPreviewActive = false; _gridPreviewSaplingPrefab = null; _gridPreviewResourcePrefab = null; } private static void PlaceCurrentGrid(Player player, GameObject placementGhost, CropInfo selectedCrop, int length, int width, float spacing) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_004c: 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) //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_0089: 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_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) //IL_0070: 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_0079: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)placementGhost == (Object)null || selectedCrop == null) { return; } Vector3 position = placementGhost.transform.position; Quaternion rotation = placementGhost.transform.rotation; Vector3 val = Vector3.ProjectOnPlane(placementGhost.transform.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f) { Vector3 val2 = Vector3.ProjectOnPlane(((Component)player).transform.forward, Vector3.up); normalized = ((Vector3)(ref val2)).normalized; } Vector3 val3 = Vector3.Cross(Vector3.up, normalized); Vector3 normalized2 = ((Vector3)(ref val3)).normalized; int num = 0; int num2 = length * width; for (int i = 0; i < length; i++) { for (int j = 0; j < width; j++) { if (!ConsumeOneResource(player, selectedCrop.ResourcePrefab)) { ShowCenterMessage("Grid Plant: planted " + num + "/" + num2 + " (out of resources in inventory/chests)"); return; } Vector3 position2 = position + normalized * ((float)i * spacing) + normalized2 * ((float)j * spacing); position2 = SnapPlantToGround(position2); if (!IsPlantPositionClear(player, position2, Mathf.Min(0.55f, spacing * 0.35f))) { RefundOneResource(player, selectedCrop.ResourcePrefab); } else if (SpawnSapling(selectedCrop.SaplingPrefab, position2, rotation)) { num++; } else { RefundOneResource(player, selectedCrop.ResourcePrefab); } } } ShowCenterMessage("Grid Plant: planted " + num + "/" + num2); } private static GameObject GetPlacementGhost(Player player) { if ((Object)(object)player == (Object)null) { return null; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_placementGhost"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(player); return (GameObject)((value is GameObject) ? value : null); } } catch { } return null; } private static Vector3 SnapPlantToGround(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) try { Heightmap val = Heightmap.FindHeightmap(position); if ((Object)(object)val != (Object)null) { float num = 0f; MethodInfo methodInfo = AccessTools.Method(typeof(Heightmap), "GetHeight", new Type[2] { typeof(Vector3), typeof(float).MakeByRefType() }, (Type[])null); if (methodInfo != null) { object[] array = new object[2] { position, num }; if (!(methodInfo.Invoke(val, array) is int num2) || num2 != 0) { position.y = Convert.ToSingle(array[1]); return position; } } MethodInfo methodInfo2 = AccessTools.Method(typeof(Heightmap), "GetWorldHeight", new Type[1] { typeof(Vector3) }, (Type[])null); if (methodInfo2 != null) { object obj = methodInfo2.Invoke(val, new object[1] { position }); if (obj != null) { position.y = Convert.ToSingle(obj); return position; } } } } catch { } try { RaycastHit[] array2 = Physics.RaycastAll(position + Vector3.up * 20f, Vector3.down, 50f, -1, (QueryTriggerInteraction)1); float num3 = float.NegativeInfinity; bool flag = false; for (int i = 0; i < array2.Length; i++) { Collider collider = ((RaycastHit)(ref array2[i])).collider; if (!((Object)(object)collider == (Object)null)) { Heightmap componentInParent = ((Component)collider).GetComponentInParent<Heightmap>(); if (!((Object)(object)componentInParent == (Object)null) && (!flag || ((RaycastHit)(ref array2[i])).point.y > num3)) { flag = true; num3 = ((RaycastHit)(ref array2[i])).point.y; } } } if (flag) { position.y = num3; } } catch { } return position; } internal static bool ConsumeOneResource(Player player, string resourcePrefab) { if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(resourcePrefab)) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (TryConsumeFromInventory(inventory, resourcePrefab)) { return true; } RefreshNearbyContainers(player); for (int i = 0; i < CachedNearbyContainers.Count; i++) { Container val = CachedNearbyContainers[i]; if (!((Object)(object)val == (Object)null)) { Inventory val2 = null; try { val2 = val.GetInventory(); } catch { } if (val2 != null && TryConsumeFromInventory(val2, resourcePrefab)) { return true; } } } return false; } private static bool TryConsumeFromInventory(Inventory inventory, string resourcePrefab) { if (inventory == null) { return false; } try { List<ItemData> allItems = inventory.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; if (val == null || (Object)(object)val.m_dropPrefab == (Object)null) { continue; } string a = NormalizePrefabName(((Object)val.m_dropPrefab).name); if (string.Equals(a, resourcePrefab, StringComparison.OrdinalIgnoreCase) && val.m_stack > 0) { val.m_stack--; if (val.m_stack <= 0) { RemoveInventoryItemReflective(inventory, val); } else { NotifyInventoryChanged(inventory); } return true; } } } catch { } return false; } private static void RefreshNearbyContainers(Player player) { //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_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_0022: 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_0050: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } float time = Time.time; Vector3 position = ((Component)player).transform.position; Vector3 val = position - _lastContainerRefreshPosition; bool flag = ((Vector3)(ref val)).sqrMagnitude > 4f; if (time < _nextContainerRefresh && !flag) { return; } _nextContainerRefresh = time + 0.5f; _lastContainerRefreshPosition = position; CachedNearbyContainers.Clear(); float num = ((FarmAssistChestRange == null) ? 20f : Mathf.Clamp(FarmAssistChestRange.Value, 1f, 50f)); float num2 = num * num; List<Container> list = new List<Container>(); foreach (Container knownContainer in KnownContainers) { if ((Object)(object)knownContainer == (Object)null) { list.Add(knownContainer); continue; } try { Vector3 val2 = ((Component)knownContainer).transform.position - position; if (((Vector3)(ref val2)).sqrMagnitude <= num2) { CachedNearbyContainers.Add(knownContainer); } } catch { } } for (int i = 0; i < list.Count; i++) { KnownContainers.Remove(list[i]); } } internal static void RefundOneResource(Player player, string resourcePrefab) { //IL_0064: 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_006e: 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) if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(resourcePrefab)) { return; } GameObject networkPrefab = GetNetworkPrefab(resourcePrefab); if ((Object)(object)networkPrefab == (Object)null) { return; } ItemDrop component = networkPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null) { return; } try { ItemData val = component.m_itemData.Clone(); val.m_stack = 1; if (((Humanoid)player).GetInventory().AddItem(val)) { return; } GameObject val2 = Object.Instantiate<GameObject>(networkPrefab, ((Component)player).transform.position + Vector3.up, Quaternion.identity); if ((Object)(object)val2 != (Object)null) { ItemDrop component2 = val2.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null) { component2.m_itemData.m_stack = 1; } } } catch { } } internal static bool SpawnSapling(string prefabName, Vector3 position, Quaternion rotation) { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(prefabName)) { return false; } try { object zNetSceneInstance = GetZNetSceneInstance(); if (zNetSceneInstance != null) { MethodInfo[] methods = typeof(ZNetScene).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "Instantiate") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 3 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion)) { object obj = methodInfo.Invoke(zNetSceneInstance, new object[3] { prefabName, position, rotation }); if (obj is GameObject) { FinalizeSpawnedPlant((GameObject)((obj is GameObject) ? obj : null)); return true; } } if (parameters.Length != 3 || !(parameters[0].ParameterType == typeof(GameObject)) || !(parameters[1].ParameterType == typeof(Vector3)) || !(parameters[2].ParameterType == typeof(Quaternion))) { continue; } GameObject networkPrefab = GetNetworkPrefab(prefabName); if (!((Object)(object)networkPrefab == (Object)null)) { object obj2 = methodInfo.Invoke(zNetSceneInstance, new object[3] { networkPrefab, position, rotation }); if (obj2 is GameObject) { FinalizeSpawnedPlant((GameObject)((obj2 is GameObject) ? obj2 : null)); return true; } } } } } catch { } GameObject networkPrefab2 = GetNetworkPrefab(prefabName); if ((Object)(object)networkPrefab2 == (Object)null) { return false; } try { GameObject val = Object.Instantiate<GameObject>(networkPrefab2, position, rotation); if ((Object)(object)val == (Object)null) { return false; } FinalizeSpawnedPlant(val); return true; } catch { return false; } } private static object GetZNetSceneInstance() { try { FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetScene), "instance"); if (fieldInfo != null) { object value = fieldInfo.GetValue(null); if (value != null) { return value; } } } catch { } try { PropertyInfo property = typeof(ZNetScene).GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(null, null); } } catch { } return null; } private static void FinalizeSpawnedPlant(GameObject planted) { if ((Object)(object)planted == (Object)null) { return; } try { ZNetView component = planted.GetComponent<ZNetView>(); if (!((Object)(object)component != (Object)null)) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(ZNetView), "IsOwner", (Type[])null, (Type[])null); bool flag = false; if (methodInfo != null) { object obj = methodInfo.Invoke(component, null); if (obj is bool) { flag = (bool)obj; } } if (!flag) { MethodInfo methodInfo2 = AccessTools.Method(typeof(ZNetView), "ClaimOwnership", (Type[])null, (Type[])null); if (methodInfo2 != null) { methodInfo2.Invoke(component, null); } } } catch { } } private static GameObject GetNetworkPrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return null; } try { Type typeFromHandle = typeof(ZNetScene); FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, "instance"); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(null) : null); if (obj == null) { PropertyInfo property = typeFromHandle.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { obj = property.GetValue(null, null); } } if (obj == null) { return null; } MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "GetPrefab", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo == null) { return null; } object? obj2 = methodInfo.Invoke(obj, new object[1] { prefabName }); return (GameObject)((obj2 is GameObject) ? obj2 : null); } catch { return null; } } private static void RemoveInventoryItemReflective(Inventory inventory, ItemData item) { if (inventory == null || item == null) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(inventory, new object[1] { item }); } } catch { } NotifyInventoryChanged(inventory); } private static void NotifyInventoryChanged(Inventory inventory) { if (inventory == null) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(inventory, null); } } catch { } } private static void ShowCenterMessage(string text) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } try { MethodInfo[] methods = typeof(Character).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "Message") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length < 2 || parameters[0].ParameterType != typeof(MessageType) || parameters[1].ParameterType != typeof(string)) { continue; } object[] array = new object[parameters.Length]; array[0] = (object)(MessageType)2; array[1] = text; for (int j = 2; j < array.Length; j++) { Type parameterType = parameters[j].ParameterType; if (parameterType == typeof(int)) { array[j] = 0; } else if (parameterType == typeof(float)) { array[j] = 0f; } else if (parameterType == typeof(bool)) { array[j] = false; } else { array[j] = null; } } methodInfo.Invoke(localPlayer, array); break; } } catch { } } internal static string NormalizePrefabName(string value) { if (string.IsNullOrEmpty(value)) { return ""; } string text = value.Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } } [HarmonyPatch] internal static class FarmAssistPickup { internal static int MassHarvestFrame = -1; private static readonly FieldInfo InteractMaskField = AccessTools.Field(typeof(Player), "m_interactMask"); private static readonly MethodInfo ExtractMethod = AccessTools.Method(typeof(Beehive), "Extract", (Type[])null, (Type[])null); private static bool FarmAssistHotkeyPressed { get { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0044: Unknown result type (might be due to invalid IL or missing references) if (LootheimPlugin.MassActionHotkey == null || LootheimPlugin.ControllerPickupHotkey == null) { return false; } KeyboardShortcut value = LootheimPlugin.MassActionHotkey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; KeyboardShortcut value2 = LootheimPlugin.ControllerPickupHotkey.Value; KeyCode mainKey2 = ((KeyboardShortcut)(ref value2)).MainKey; if ((int)mainKey == 0 || !Input.GetKey(mainKey)) { if ((int)mainKey2 != 0) { return Input.GetKey(mainKey2); } return false; } return true; } } [HarmonyPatch(typeof(Player), "Interact")] [HarmonyPrefix] private static void Prefix(Player __instance, GameObject go, bool hold, bool alt) { //IL_0092: 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_01f4: Unknown result type (might be due to invalid IL or missing references) if (LootheimPlugin.Enabled == null || !LootheimPlugin.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)go == (Object)null || ((Character)__instance).InAttack() || ((Character)__instance).InDodge() || hold || !FarmAssistHotkeyPressed) { return; } Interactable componentInParent = go.GetComponentInParent<Interactable>(); Pickable val = (Pickable)(object)((componentInParent is Pickable) ? componentInParent : null); if ((Object)(object)val != (Object)null) { MassHarvestFrame = Time.frameCount; int num = -1; try { if (InteractMaskField != null) { num = (int)InteractMaskField.GetValue(__instance); } } catch { } Collider[] array = Physics.OverlapSphere(go.transform.position, LootheimPlugin.MassInteractRange.Value, num); foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null)) { Pickable componentInParent2 = ((Component)val2).gameObject.GetComponentInParent<Pickable>(); if (!((Object)(object)componentInParent2 == (Object)null) && !((Object)(object)componentInParent2 == (Object)(object)val) && (Object)(object)componentInParent2.m_itemPrefab != (Object)null && (Object)(object)val.m_itemPrefab != (Object)null && ((Object)componentInParent2.m_itemPrefab).name == ((Object)val.m_itemPrefab).name) { componentInParent2.Interact((Humanoid)(object)__instance, false, alt); } } } return; } Beehive val3 = (Beehive)(object)((componentInParent is Beehive) ? componentInParent : null); if (!((Object)(object)val3 != (Object)null)) { return; } int num2 = -1; try { if (InteractMaskField != null) { num2 = (int)InteractMaskField.GetValue(__instance); } } catch { } Collider[] array2 = Physics.OverlapSphere(go.transform.position, LootheimPlugin.MassInteractRange.Value, num2); foreach (Collider val4 in array2) { if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).gameObject == (Object)null) { continue; } Beehive componentInParent3 = ((Component)val4).gameObject.GetComponentInParent<Beehive>(); if ((Object)(object)componentInParent3 == (Object)null || (Object)(object)componentInParent3 == (Object)(object)val3 || !PrivateArea.CheckAccess(((Component)componentInParent3).transform.position, 0f, true, false)) { continue; } try { if (ExtractMethod != null) { ExtractMethod.Invoke(componentInParent3, null); } } catch { } } } } [HarmonyPatch(typeof(Pickable), "Interact", new Type[] { typeof(Humanoid), typeof(bool), typeof(bool) })] internal static class FarmAssistMassReplantPatch { private sealed class ReplantState { internal Player Player; internal LootheimPlugin.CropInfo Crop; internal Vector3 Position; internal Quaternion Rotation; } private static void Prefix(Pickable __instance, Humanoid character, ref ReplantState __state) { //IL_00b0: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) __state = null; if ((Object)(object)__instance == (Object)null || (Object)(object)character == (Object)null || LootheimPlugin.Enabled == null || !LootheimPlugin.Enabled.Value || LootheimPlugin.AutoReplant == null || !LootheimPlugin.AutoReplant.Value || FarmAssistPickup.MassHarvestFrame != Time.frameCount) { return; } Player val = (Player)(object)((character is Player) ? character : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && !LootheimPlugin.IsAlreadyPicked(__instance)) { string key = LootheimPlugin.NormalizePrefabName(((Object)((Component)__instance).gameObject).name); if (LootheimPlugin.FarmCrops.TryGetValue(key, out var value) && value != null) { __state = new ReplantState { Player = val, Crop = value, Position = ((Component)__instance).transform.position, Rotation = ((Component)__instance).transform.rotation }; } } } private static void Postfix(bool __result, ReplantState __state) { //IL_0042: 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) if (__result && __state != null && !((Object)(object)__state.Player == (Object)null) && __state.Crop != null && LootheimPlugin.ConsumeOneResource(__state.Player, __state.Crop.ResourcePrefab) && !LootheimPlugin.SpawnSapling(__state.Crop.SaplingPrefab, __state.Position, __state.Rotation)) { LootheimPlugin.RefundOneResource(__state.Player, __state.Crop.ResourcePrefab); } } } [HarmonyPatch] internal static class FarmAssistPlant { private static readonly FieldInfo NoPlacementCostField = AccessTools.Field(typeof(Player), "m_noPlacementCost"); private static readonly FieldInfo PlacementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); private static readonly FieldInfo BuildPiecesField = AccessTools.Field(typeof(Player), "m_buildPieces"); private static readonly MethodInfo GetRightItemMethod = AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null); private static Vector3 PlacedPosition; private static Quaternion PlacedRotation; private static Piece PlacedPiece; private static bool PlaceSuccessful; private static int? FarmRotation; private static readonly int PlantSpaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" }); private static GameObject[] PlacementGhosts = (GameObject[])(object)new GameObject[1]; private static Piece FakeResourcePiece; private static bool IsHotKeyPressed { get { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_0049: 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_004c: 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) if (LootheimPlugin.Enabled == null || !LootheimPlugin.Enabled.Value || LootheimPlugin.MassActionHotkey == null || LootheimPlugin.ControllerPickupHotkey == null) { return false; } KeyboardShortcut value = LootheimPlugin.MassActionHotkey.Value; KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey; KeyboardShortcut value2 = LootheimPlugin.ControllerPickupHotkey.Value; KeyCode mainKey2 = ((KeyboardShortcut)(ref value2)).MainKey; if ((int)mainKey == 0 || !Input.GetKey(mainKey)) { if ((int)mainKey2 != 0) { return Input.GetKey(mainKey2); } return false; } return true; } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] [HarmonyPrefix] private static void TryPlacePiecePrefix(int ___m_placeRotation) { if (IsHotKeyPressed && !FarmRotation.HasValue) { FarmRotation = ___m_placeRotation; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "TryPlacePiece")] private static void TryPlacePiecePostfix(Player __instance, ref bool __result, Piece piece, ref int ___m_placeRotation) { //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_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) PlaceSuccessful = __result; if (__result) { GameObject val = null; try { if (PlacementGhostField != null) { object? value = PlacementGhostField.GetValue(__instance); val = (GameObject)((value is GameObject) ? value : null); } } catch { } if ((Object)(object)val != (Object)null) { PlacedPosition = val.transform.position; PlacedRotation = val.transform.rotation; PlacedPiece = piece; } } if (IsHotKeyPressed && FarmRotation.HasValue) { ___m_placeRotation = FarmRotation.Value; } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] [HarmonyPrefix] private static void UpdatePlacementPrefix(bool takeInput, float dt, ref int ___m_placeRotation) { PlaceSuccessful = false; if (IsHotKeyPressed && FarmRotation.HasValue) { ___m_placeRotation = FarmRotation.Value; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static void UpdatePlacementPostfix(Player __instance, bool takeInput, float dt, int ___m_placeRotation) { //IL_0096: 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_00bd: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: 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_01f1: 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) if (IsHotKeyPressed) { FarmRotation = ___m_placeRotation; } if (!PlaceSuccessful || (Object)(object)PlacedPiece == (Object)null) { return; } Plant component = ((Component)PlacedPiece).gameObject.GetComponent<Plant>(); if ((!IsCultivatorPlacement(__instance, ((Component)PlacedPiece).gameObject) && (Object)(object)component == (Object)null) || !IsHotKeyPressed) { return; } Heightmap val = Heightmap.FindHeightmap(PlacedPosition); if ((Object)(object)val == (Object)null) { return; } PieceTable val2 = null; try { if (BuildPiecesField != null) { object? value = BuildPiecesField.GetValue(__instance); val2 = (PieceTable)((value is PieceTable) ? value : null); } } catch { } List<Vector3> list = BuildPlantingGridPositions(PlacedPosition, ((Component)PlacedPiece).gameObject, PlacedRotation); for (int i = 0; i < list.Count; i++) { Vector3 val3 = list[i]; if ((PlacedPiece.m_cultivatedGroundOnly && !val.IsCultivated(val3)) || PlacedPosition == val3) { continue; } ItemData rightItem = GetRightItem(__instance); if (rightItem == null) { continue; } if (!LootheimPlugin.IgnoreStamina.Value && !((Character)__instance).HaveStamina(rightItem.m_shared.m_attack.m_attackStamina)) { if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.StaminaBarUppgradeFlash(); } break; } bool flag = false; try { if (NoPlacementCostField != null) { flag = (bool)NoPlacementCostField.GetValue(__instance); } } catch { } if (!flag && !__instance.HaveRequirements(PlacedPiece, (RequirementMode)0)) { break; } if (!HasGrowSpace(val3, ((Component)PlacedPiece).gameObject)) { continue; } GameObject val4 = Object.Instantiate<GameObject>(((Component)PlacedPiece).gameObject, val3, PlacedRotation); Piece component2 = val4.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { SetPieceCreatorSafe(component2, __instance); } PlacedPiece.m_placeEffect.Create(val3, PlacedRotation, val4.transform, 1f, -1, default(ZDOID)); if ((Object)(object)Game.instance != (Object)null) { Game.instance.IncrementPlayerStat((PlayerStatType)2, 1f, false); } __instance.ConsumeResources(PlacedPiece.m_resources, 0, -1, 1); if (!LootheimPlugin.IgnoreStamina.Value) { ((Character)__instance).UseStamina(rightItem.m_shared.m_attack.m_attackStamina); } if ((Object)(object)val2 != (Object)null) { ((Character)__instance).RaiseSkill(val2.m_skill, 1f); } if (!LootheimPlugin.IgnoreDurability.Value && rightItem.m_shared.m_useDurability) { rightItem.m_durability -= rightItem.m_shared.m_useDurabilityDrain; if (rightItem.m_durability <= 0f) { break; } } } } private static void SetPieceCreatorSafe(Piece piece, Player player) { if ((Object)(object)piece == (Object)null || (Object)(object)player == (Object)null) { return; } try { MethodInfo[] methods = typeof(Piece).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); long playerID = player.GetPlayerID(); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "SetCreator") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(long)) { methodInfo.Invoke(piece, new object[1] { playerID }); break; } if (parameters.Length != 2 || !(parameters[0].ParameterType == typeof(long))) { continue; } object obj = null; try { Type type = Type.GetType("Splatform.PlatformManager, assembly_utils", throwOnError: false); if (type != null) { PropertyInfo property = type.GetProperty("DistributionPlatform", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj2 = ((property == null) ? null : property.GetValue(null, null)); if (obj2 != null) { PropertyInfo property2 = obj2.GetType().GetProperty("LocalUser", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj3 = ((property2 == null) ? null : property2.GetValue(obj2, null)); if (obj3 != null) { PropertyInfo property3 = obj3.GetType().GetProperty("PlatformUserID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property3 != null) { obj = property3.GetValue(obj3, null); } } } } } catch { } if (obj != null && parameters[1].ParameterType.IsInstanceOfType(obj)) { methodInfo.Invoke(piece, new object[2] { playerID, obj }); break; } } } catch { } } private static bool IsCultivatorPlacement(Player player, GameObject placementObject) { if ((Object)(object)player == (Object)null || (Object)(object)placementObject == (Object)null) { return false; } ItemData rightItem = GetRightItem(player); if (rightItem == null || rightItem.m_shared == null) { return false; } if ((Object)(object)rightItem.m_shared.m_buildPieces != (Object)null) { try { List<GameObject> pieces = rightItem.m_shared.m_buildPieces.m_pieces; if (pieces != null) { string text = ((Object)placementObject).name.Replace("(Clone)", ""); for (int i = 0; i < pieces.Count; i++) { GameObject val = pieces[i]; if ((Object)(object)val != (Object)null && ((Object)val).name == text) { string text2 = rightItem.m_shared.m_name ?? ""; return text2.IndexOf("cultivator", StringComparison.OrdinalIgnoreCase) >= 0; } } } } catch { } } string text3 = rightItem.m_shared.m_name ?? ""; return text3.IndexOf("cultivator", StringComparison.OrdinalIgnoreCase) >= 0; } private static float GetFarmAssistSpacing(GameObject placementObject) { if ((Object)(object)placementObject == (Object)null) { return 1f; } Plant component = placementObject.GetComponent<Plant>(); if ((Object)(object)component != (Object)null) { return Mathf.Max(0.5f, component.m_growRadius * 2f); } float num = ((LootheimPlugin.NonPlantFloraSpacing == null) ? 1f : LootheimPlugin.NonPlantFloraSpacing.Value); return Mathf.Clamp(num, 0.5f, 4f); } private static ItemData GetRightItem(Player player) { if ((Object)(object)player == (Object)null || GetRightItemMethod == null) { return null; } try { object? obj = GetRightItemMethod.Invoke(player, new object[0]); return (ItemData)((obj is ItemData) ? obj : null); } catch { return null; } } private static List<Vector3> BuildPlantingGridPositions(Vector3 originPos, GameObject placementObject, Quaternion rotation) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0046: 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) //IL_0051: 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_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_0067: 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_006f: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_00ec: 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_00f0: 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_00a0: 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_00bd: Unknown result type (might be due to invalid IL or missing references) float farmAssistSpacing = GetFarmAssistSpacing(placementObject); int num = Mathf.Max(1, LootheimPlugin.PlantGridWidth.Value); int num2 = Mathf.Max(1, LootheimPlugin.PlantGridLength.Value); List<Vector3> list = new List<Vector3>(num * num2); Vector3 val = rotation * Vector3.left * farmAssistSpacing; Vector3 val2 = rotation * Vector3.forward * farmAssistSpacing; Vector3 val3 = originPos; if (LootheimPlugin.GridAnchorLength.Value) { val3 -= val2 * (float)(num2 / 2); } if (LootheimPlugin.GridAnchorWidth.Value) { val3 -= val * (float)(num / 2); } for (int i = 0; i < num2; i++) { Vector3 val4 = val3; for (int j = 0; j < num; j++) { try { if ((Object)(object)ZoneSystem.instance != (Object)null) { val4.y = ZoneSystem.instance.GetGroundHeight(val4); } } catch { } list.Add(val4); val4 += val; } val3 += val2; } return list; } private static bool HasGrowSpace(Vector3 newPos, GameObject go) { //IL_004c: 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_0057: 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) if ((Object)(object)go == (Object)null) { return true; } Plant component = go.GetComponent<Plant>(); float num; if ((Object)(object)component != (Object)null) { num = Mathf.Max(0.25f, component.m_growRadius); } else { float farmAssistSpacing = GetFarmAssistSpacing(go); num = Mathf.Clamp(farmAssistSpacing * 0.4f, 0.25f, 1.5f); } Collider[] array = Physics.OverlapSphere(newPos + Vector3.up * 0.25f, num, PlantSpaceMask, (QueryTriggerInteraction)1); if (array == null || array.Length == 0) { return true; } foreach (Collider val in array) { if (!((Object)(object)val == (Object)null)) { Heightmap componentInParent = ((Component)val).GetComponentInParent<Heightmap>(); if (!((Object)(object)componentInParent != (Object)null) && !((Object)(object)((Component)val).transform == (Object)(object)go.transform) && !((Component)val).transform.IsChildOf(go.transform)) { return false; } } } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] private static void SetupPlacementGhostPrefix(Player __instance, int ___m_placeRotation) { if (IsHotKeyPressed && !FarmRotation.HasValue) { FarmRotation = ___m_placeRotation; } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] private static void SetupPlacementGhostPostfix(Player __instance, ref int ___m_placeRotation) { if (IsHotKeyPressed && FarmRotation.HasValue) { ___m_placeRotation = FarmRotation.Value; } DestroyGhosts(); } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] private static void UpdatePlacementGhostPostfix(Player __instance, bool flashGuardStone) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; try { if (PlacementGhostField != null) { object? value = PlacementGhostField.GetValue(__instance); val = (GameObject)((value is GameObject) ? value : null); } } catch { } if ((Object)(object)val == (Object)null || !val.activeSelf) { SetGhostsActive(active: false); return; } if (!IsHotKeyPressed) { SetGhostsActive(active: false); return; } Plant component = val.GetComponent<Plant>(); if (!IsCultivatorPlacement(__instance, val) && (Object)(object)component == (Object)null) { SetGhostsActive(active: false); return; } if (!EnsureGhostsBuilt(__instance)) { SetGhostsActive(active: false); return; } Piece component2 = val.GetComponent<Piece>(); if ((Object)(object)component2 == (Object)null || (Object)(object)FakeResourcePiece == (Object)null) { return; } Requirement val2 = ((IEnumerable<Requirement>)component2.m_resources).FirstOrDefault((Func<Requirement, bool>)((Requirement r) => r != null && (Object)(object)r.m_resItem != (Object)null && r.m_amount > 0)); if (val2 == null) { return; } FakeResourcePiece.m_resources[0].m_resItem = val2.m_resItem; FakeResourcePiece.m_resources[0].m_amount = val2.m_amount; float num = __instance.GetStamina(); ItemData rightItem = GetRightItem(__instance); if (rightItem == null) { return; } Heightmap val3 = Heightmap.FindHeightmap(val.transform.position); if ((Object)(object)val3 == (Object)null) { return; } List<Vector3> list = BuildPlantingGridPositions(val.transform.position, val, val.transform.rotation); for (int num2 = 0; num2 < PlacementGhosts.Length && num2 < list.Count; num2++) { Vector3 val4 = list[num2]; GameObject val5 = PlacementGhosts[num2]; if ((Object)(object)val5 == (Object)null) { continue; } if (val.transform.position == val4) { val5.SetActive(false); continue; } Requirement obj2 = FakeResourcePiece.m_resources[0]; obj2.m_amount += val2.m_amount; val5.transform.position = val4; val5.transform.rotation = val.transform.rotation; val5.SetActive(true); bool invalidPlacementHeightlight = false; if (component2.m_cultivatedGroundOnly && !val3.IsCultivated(val4)) { invalidPlacementHeightlight = true; } else if (!HasGrowSpace(val4, val)) { invalidPlacementHeightlight = true; } else if (!LootheimPlugin.IgnoreStamina.Value && num < rightItem.m_shared.m_attack.m_attackStamina) { if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.StaminaBarUppgradeFlash(); } invalidPlacementHeightlight = true; } else { bool flag = false; try { if (NoPlacementCostField != null) { flag = (bool)NoPlacementCostField.GetValue(__instance); } } catch { } if (!flag && !__instance.HaveRequirements(FakeResourcePiece, (RequirementMode)0)) { invalidPlacementHeightlight = true; } } num -= rightItem.m_shared.m_attack.m_attackStamina; Piece component3 = val5.GetComponent<Piece>(); if ((Object)(object)component3 != (Object)null) { component3.SetInvalidPlacementHeightlight(invalidPlacementHeightlight); } } } private static bool EnsureGhostsBuilt(Player player) { //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown int num = Mathf.Max(1, LootheimPlugin.PlantGridWidth.Value) * Mathf.Max(1, LootheimPlugin.PlantGridLength.Value); if (PlacementGhosts == null || PlacementGhosts.Length == 0 || (Object)(object)PlacementGhosts[0] == (Object)null || PlacementGhosts.Length != num) { DestroyGhosts(); if (PlacementGhosts == null || PlacementGhosts.Length != num) { PlacementGhosts = (GameObject[])(object)new GameObject[num]; } PieceTable val = null; try { if (BuildPiecesField != null) { object? value = BuildPiecesField.GetValue(player); val = (PieceTable)((value is PieceTable) ? value : null); } } catch { } GameObject val2 = (((Object)(object)val == (Object)null) ? null : val.GetSelectedPrefab()); if ((Object)(object)val2 == (Object)null) { return false; } Piece component = val2.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && component.m_repairPiece) { return false; } for (int i = 0; i < PlacementGhosts.Length; i++) { PlacementGhosts[i] = SetupMyGhost(player, val2); } } if ((Object)(object)FakeResourcePiece == (Object)null) { if (PlacementGhosts == null || PlacementGhosts.Length == 0 || (Object)(object)PlacementGhosts[0] == (Object)null) { return false; } FakeResourcePiece = PlacementGhosts[0].GetComponent<Piece>(); if ((Object)(object)FakeResourcePiece == (Object)null) { return false; } FakeResourcePiece.m_dlc = string.Empty; FakeResourcePiece.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement() }; } return true; } private static void DestroyGhosts() { if (PlacementGhosts != null) { for (int i = 0; i < PlacementGhosts.Length; i++) { if ((Object)(object)PlacementGhosts[i] != (Object)null) { Object.Destroy((Object)(object)PlacementGhosts[i]); PlacementGhosts[i] = null; } } } FakeResourcePiece = null; } private static void SetGhostsActive(bool active) { if (PlacementGhosts == null) { return; } for (int i = 0; i < PlacementGhosts.Length; i++) { if ((Object)(object)PlacementGhosts[i] != (Object)null) { PlacementGhosts[i].SetActive(active); } } } private static GameObject SetupMyGhost(Player player, GameObject prefab) { //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown ZNetView.m_forceDisableInit = true; GameObject val = Object.Instantiate<GameObject>(prefab); ZNetView.m_forceDisableInit = false; ((Object)val).name = ((Object)prefab).name; Joint[] componentsInChildren = val.GetComponentsInChildren<Joint>(); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } Rigidbody[] componentsInChildren2 = val.GetComponentsInChildren<Rigidbody>(); for (int j = 0; j < componentsInChildren2.Length; j++) { Object.Destroy((Object)(object)componentsInChildren2[j]); } int layer = LayerMask.NameToLayer("ghost"); Transform[] componentsInChildren3 = val.GetComponentsInChildren<Transform>(); for (int k = 0; k < componentsInChildren3.Length; k++) { ((Component)componentsInChildren3[k]).gameObject.layer = layer; } TerrainModifier[] componentsInChildren4 = val.GetComponentsInChildren<TerrainModifier>(); for (int l = 0; l < componentsInChildren4.Length; l++) { Object.Destroy((Object)(object)componentsInChildren4[l]); } GuidePoint[] componentsInChildren5 = val.GetComponentsInChildren<GuidePoint>(); for (int m = 0; m < componentsInChildren5.Length; m++) { Object.Destroy((Object)(object)componentsInChildren5[m]); } Light[] componentsInChildren6 = val.GetComponentsInChildren<Light>(); for (int n = 0; n < componentsInChildren6.Length; n++) { Object.Destroy((Object)(object)componentsInChildren6[n]); } Transform val2 = val.transform.Find("_GhostOnly"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(true); } MeshRenderer[] componentsInChildren7 = val.GetComponentsInChildren<MeshRenderer>(); foreach (MeshRenderer val3 in componentsInChildren7) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Renderer)val3).sharedMaterial == (Object)null)) { Material[] sharedMaterials = ((Renderer)val3).sharedMaterials; for (int num2 = 0; num2 < sharedMaterials.Length; num2++) { Material val4 = new Material(sharedMaterials[num2]); val4.SetFloat("_RippleDistance", 0f); val4.SetFloat("_ValueNoise", 0f); sharedMaterials[num2] = val4; } ((Renderer)val3).sharedMaterials = sharedMaterials; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; } } return val; } }